| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | /* | 
| 2 |  |  |  |  |  |  | * Copyright (C) the libgit2 contributors. All rights reserved. | 
| 3 |  |  |  |  |  |  | * | 
| 4 |  |  |  |  |  |  | * This file is part of libgit2, distributed under the GNU GPL v2 with | 
| 5 |  |  |  |  |  |  | * a Linking Exception. For full terms see the included COPYING file. | 
| 6 |  |  |  |  |  |  | */ | 
| 7 |  |  |  |  |  |  | #include "buffer.h" | 
| 8 |  |  |  |  |  |  | #include "posix.h" | 
| 9 |  |  |  |  |  |  | #include "git2/buffer.h" | 
| 10 |  |  |  |  |  |  | #include "buf_text.h" | 
| 11 |  |  |  |  |  |  | #include | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | /* Used as default value for git_buf->ptr so that people can always | 
| 14 |  |  |  |  |  |  | * assume ptr is non-NULL and zero terminated even for new git_bufs. | 
| 15 |  |  |  |  |  |  | */ | 
| 16 |  |  |  |  |  |  | char git_buf__initbuf[1]; | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | char git_buf__oom[1]; | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #define ENSURE_SIZE(b, d) \ | 
| 21 |  |  |  |  |  |  | if ((b)->ptr == git_buf__oom || \ | 
| 22 |  |  |  |  |  |  | ((d) > (b)->asize && git_buf_grow((b), (d)) < 0))\ | 
| 23 |  |  |  |  |  |  | return -1; | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 33829 |  |  |  |  |  | int git_buf_init(git_buf *buf, size_t initial_size) | 
| 27 |  |  |  |  |  |  | { | 
| 28 | 33829 |  |  |  |  |  | buf->asize = 0; | 
| 29 | 33829 |  |  |  |  |  | buf->size = 0; | 
| 30 | 33829 |  |  |  |  |  | buf->ptr = git_buf__initbuf; | 
| 31 |  |  |  |  |  |  |  | 
| 32 | 33829 | 50 |  |  |  |  | ENSURE_SIZE(buf, initial_size); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 33829 |  |  |  |  |  | return 0; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 | 28187 |  |  |  |  |  | int git_buf_try_grow( | 
| 38 |  |  |  |  |  |  | git_buf *buf, size_t target_size, bool mark_oom) | 
| 39 |  |  |  |  |  |  | { | 
| 40 |  |  |  |  |  |  | char *new_ptr; | 
| 41 |  |  |  |  |  |  | size_t new_size; | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 28187 | 50 |  |  |  |  | if (buf->ptr == git_buf__oom) | 
| 44 | 0 |  |  |  |  |  | return -1; | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 28187 | 100 |  |  |  |  | if (buf->asize == 0 && buf->size != 0) { | 
|  |  | 50 |  |  |  |  |  | 
| 47 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "cannot grow a borrowed buffer"); | 
| 48 | 0 |  |  |  |  |  | return GIT_EINVALID; | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 28187 | 100 |  |  |  |  | if (!target_size) | 
| 52 | 2 |  |  |  |  |  | target_size = buf->size; | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 28187 | 100 |  |  |  |  | if (target_size <= buf->asize) | 
| 55 | 418 |  |  |  |  |  | return 0; | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 27769 | 100 |  |  |  |  | if (buf->asize == 0) { | 
| 58 | 22431 |  |  |  |  |  | new_size = target_size; | 
| 59 | 22431 |  |  |  |  |  | new_ptr = NULL; | 
| 60 |  |  |  |  |  |  | } else { | 
| 61 | 5338 |  |  |  |  |  | new_size = buf->asize; | 
| 62 |  |  |  |  |  |  | /* | 
| 63 |  |  |  |  |  |  | * Grow the allocated buffer by 1.5 to allow | 
| 64 |  |  |  |  |  |  | * re-use of memory holes resulting from the | 
| 65 |  |  |  |  |  |  | * realloc. If this is still too small, then just | 
| 66 |  |  |  |  |  |  | * use the target size. | 
| 67 |  |  |  |  |  |  | */ | 
| 68 | 5338 | 100 |  |  |  |  | if ((new_size = (new_size << 1) - (new_size >> 1)) < target_size) | 
| 69 | 1039 |  |  |  |  |  | new_size = target_size; | 
| 70 | 5338 |  |  |  |  |  | new_ptr = buf->ptr; | 
| 71 |  |  |  |  |  |  | } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | /* round allocation up to multiple of 8 */ | 
| 74 | 27769 |  |  |  |  |  | new_size = (new_size + 7) & ~7; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 27769 | 50 |  |  |  |  | if (new_size < buf->size) { | 
| 77 | 0 | 0 |  |  |  |  | if (mark_oom) { | 
| 78 | 0 | 0 |  |  |  |  | if (buf->ptr && buf->ptr != git_buf__initbuf) | 
|  |  | 0 |  |  |  |  |  | 
| 79 | 0 |  |  |  |  |  | git__free(buf->ptr); | 
| 80 | 0 |  |  |  |  |  | buf->ptr = git_buf__oom; | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 0 |  |  |  |  |  | git_error_set_oom(); | 
| 84 | 0 |  |  |  |  |  | return -1; | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 27769 |  |  |  |  |  | new_ptr = git__realloc(new_ptr, new_size); | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 27769 | 50 |  |  |  |  | if (!new_ptr) { | 
| 90 | 0 | 0 |  |  |  |  | if (mark_oom) { | 
| 91 | 0 | 0 |  |  |  |  | if (buf->ptr && (buf->ptr != git_buf__initbuf)) | 
|  |  | 0 |  |  |  |  |  | 
| 92 | 0 |  |  |  |  |  | git__free(buf->ptr); | 
| 93 | 0 |  |  |  |  |  | buf->ptr = git_buf__oom; | 
| 94 |  |  |  |  |  |  | } | 
| 95 | 0 |  |  |  |  |  | return -1; | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 27769 |  |  |  |  |  | buf->asize = new_size; | 
| 99 | 27769 |  |  |  |  |  | buf->ptr   = new_ptr; | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | /* truncate the existing buffer size if necessary */ | 
| 102 | 27769 | 50 |  |  |  |  | if (buf->size >= buf->asize) | 
| 103 | 0 |  |  |  |  |  | buf->size = buf->asize - 1; | 
| 104 | 27769 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 105 |  |  |  |  |  |  |  | 
| 106 | 27769 |  |  |  |  |  | return 0; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 27660 |  |  |  |  |  | int git_buf_grow(git_buf *buffer, size_t target_size) | 
| 110 |  |  |  |  |  |  | { | 
| 111 | 27660 |  |  |  |  |  | return git_buf_try_grow(buffer, target_size, true); | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 18 |  |  |  |  |  | int git_buf_grow_by(git_buf *buffer, size_t additional_size) | 
| 115 |  |  |  |  |  |  | { | 
| 116 |  |  |  |  |  |  | size_t newsize; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 18 | 50 |  |  |  |  | if (GIT_ADD_SIZET_OVERFLOW(&newsize, buffer->size, additional_size)) { | 
|  |  | 50 |  |  |  |  |  | 
| 119 | 0 |  |  |  |  |  | buffer->ptr = git_buf__oom; | 
| 120 | 0 |  |  |  |  |  | return -1; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 18 |  |  |  |  |  | return git_buf_try_grow(buffer, newsize, true); | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 30442 |  |  |  |  |  | void git_buf_dispose(git_buf *buf) | 
| 127 |  |  |  |  |  |  | { | 
| 128 | 30442 | 100 |  |  |  |  | if (!buf) return; | 
| 129 |  |  |  |  |  |  |  | 
| 130 | 29858 | 100 |  |  |  |  | if (buf->asize > 0 && buf->ptr != NULL && buf->ptr != git_buf__oom) | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 131 | 19555 |  |  |  |  |  | git__free(buf->ptr); | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 29858 |  |  |  |  |  | git_buf_init(buf, 0); | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 0 |  |  |  |  |  | void git_buf_free(git_buf *buf) | 
| 137 |  |  |  |  |  |  | { | 
| 138 | 0 |  |  |  |  |  | git_buf_dispose(buf); | 
| 139 | 0 |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 367 |  |  |  |  |  | void git_buf_sanitize(git_buf *buf) | 
| 142 |  |  |  |  |  |  | { | 
| 143 | 367 | 100 |  |  |  |  | if (buf->ptr == NULL) { | 
| 144 | 41 | 50 |  |  |  |  | assert(buf->size == 0 && buf->asize == 0); | 
|  |  | 50 |  |  |  |  |  | 
| 145 | 41 |  |  |  |  |  | buf->ptr = git_buf__initbuf; | 
| 146 | 326 | 100 |  |  |  |  | } else if (buf->asize > buf->size) | 
| 147 | 71 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 148 | 367 |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 14050 |  |  |  |  |  | void git_buf_clear(git_buf *buf) | 
| 151 |  |  |  |  |  |  | { | 
| 152 | 14050 |  |  |  |  |  | buf->size = 0; | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 14050 | 100 |  |  |  |  | if (!buf->ptr) { | 
| 155 | 647 |  |  |  |  |  | buf->ptr = git_buf__initbuf; | 
| 156 | 647 |  |  |  |  |  | buf->asize = 0; | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 14050 | 100 |  |  |  |  | if (buf->asize > 0) | 
| 160 | 7997 |  |  |  |  |  | buf->ptr[0] = '\0'; | 
| 161 | 14050 |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 6902 |  |  |  |  |  | int git_buf_set(git_buf *buf, const void *data, size_t len) | 
| 164 |  |  |  |  |  |  | { | 
| 165 |  |  |  |  |  |  | size_t alloclen; | 
| 166 |  |  |  |  |  |  |  | 
| 167 | 6902 | 100 |  |  |  |  | if (len == 0 || data == NULL) { | 
|  |  | 50 |  |  |  |  |  | 
| 168 | 11 |  |  |  |  |  | git_buf_clear(buf); | 
| 169 |  |  |  |  |  |  | } else { | 
| 170 | 6891 | 100 |  |  |  |  | if (data != buf->ptr) { | 
| 171 | 5828 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, len, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 172 | 5828 | 50 |  |  |  |  | ENSURE_SIZE(buf, alloclen); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 173 | 5828 |  |  |  |  |  | memmove(buf->ptr, data, len); | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 6891 |  |  |  |  |  | buf->size = len; | 
| 177 | 6891 | 50 |  |  |  |  | if (buf->asize > buf->size) | 
| 178 | 6891 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | } | 
| 181 | 6902 |  |  |  |  |  | return 0; | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 0 |  |  |  |  |  | int git_buf_is_binary(const git_buf *buf) | 
| 185 |  |  |  |  |  |  | { | 
| 186 | 0 |  |  |  |  |  | return git_buf_text_is_binary(buf); | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 0 |  |  |  |  |  | int git_buf_contains_nul(const git_buf *buf) | 
| 190 |  |  |  |  |  |  | { | 
| 191 | 0 |  |  |  |  |  | return git_buf_text_contains_nul(buf); | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 | 2839 |  |  |  |  |  | int git_buf_sets(git_buf *buf, const char *string) | 
| 195 |  |  |  |  |  |  | { | 
| 196 | 2839 | 50 |  |  |  |  | return git_buf_set(buf, string, string ? strlen(string) : 0); | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  |  | 
| 199 | 18389 |  |  |  |  |  | int git_buf_putc(git_buf *buf, char c) | 
| 200 |  |  |  |  |  |  | { | 
| 201 |  |  |  |  |  |  | size_t new_size; | 
| 202 | 18389 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, 2); | 
|  |  | 50 |  |  |  |  |  | 
| 203 | 18389 | 50 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 204 | 18389 |  |  |  |  |  | buf->ptr[buf->size++] = c; | 
| 205 | 18389 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 206 | 18389 |  |  |  |  |  | return 0; | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 16 |  |  |  |  |  | int git_buf_putcn(git_buf *buf, char c, size_t len) | 
| 210 |  |  |  |  |  |  | { | 
| 211 |  |  |  |  |  |  | size_t new_size; | 
| 212 | 16 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len); | 
|  |  | 50 |  |  |  |  |  | 
| 213 | 16 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 214 | 16 | 50 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 215 | 16 |  |  |  |  |  | memset(buf->ptr + buf->size, c, len); | 
| 216 | 16 |  |  |  |  |  | buf->size += len; | 
| 217 | 16 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 218 | 16 |  |  |  |  |  | return 0; | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 14100 |  |  |  |  |  | int git_buf_put(git_buf *buf, const char *data, size_t len) | 
| 222 |  |  |  |  |  |  | { | 
| 223 | 14100 | 100 |  |  |  |  | if (len) { | 
| 224 |  |  |  |  |  |  | size_t new_size; | 
| 225 |  |  |  |  |  |  |  | 
| 226 | 13464 | 50 |  |  |  |  | assert(data); | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 13464 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len); | 
|  |  | 50 |  |  |  |  |  | 
| 229 | 13464 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 230 | 13464 | 50 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 231 | 13464 |  |  |  |  |  | memmove(buf->ptr + buf->size, data, len); | 
| 232 | 13464 |  |  |  |  |  | buf->size += len; | 
| 233 | 13464 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 234 |  |  |  |  |  |  | } | 
| 235 | 14100 |  |  |  |  |  | return 0; | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  |  | 
| 238 | 7733 |  |  |  |  |  | int git_buf_puts(git_buf *buf, const char *string) | 
| 239 |  |  |  |  |  |  | { | 
| 240 | 7733 | 50 |  |  |  |  | assert(string); | 
| 241 | 7733 |  |  |  |  |  | return git_buf_put(buf, string, strlen(string)); | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | static const char base64_encode[] = | 
| 245 |  |  |  |  |  |  | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 
| 246 |  |  |  |  |  |  |  | 
| 247 | 0 |  |  |  |  |  | int git_buf_encode_base64(git_buf *buf, const char *data, size_t len) | 
| 248 |  |  |  |  |  |  | { | 
| 249 | 0 |  |  |  |  |  | size_t extra = len % 3; | 
| 250 |  |  |  |  |  |  | uint8_t *write, a, b, c; | 
| 251 | 0 |  |  |  |  |  | const uint8_t *read = (const uint8_t *)data; | 
| 252 | 0 |  |  |  |  |  | size_t blocks = (len / 3) + !!extra, alloclen; | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&blocks, blocks, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 255 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 4); | 
|  |  | 0 |  |  |  |  |  | 
| 256 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 257 |  |  |  |  |  |  |  | 
| 258 | 0 | 0 |  |  |  |  | ENSURE_SIZE(buf, alloclen); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 259 | 0 |  |  |  |  |  | write = (uint8_t *)&buf->ptr[buf->size]; | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | /* convert each run of 3 bytes into 4 output bytes */ | 
| 262 | 0 | 0 |  |  |  |  | for (len -= extra; len > 0; len -= 3) { | 
| 263 | 0 |  |  |  |  |  | a = *read++; | 
| 264 | 0 |  |  |  |  |  | b = *read++; | 
| 265 | 0 |  |  |  |  |  | c = *read++; | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 0 |  |  |  |  |  | *write++ = base64_encode[a >> 2]; | 
| 268 | 0 |  |  |  |  |  | *write++ = base64_encode[(a & 0x03) << 4 | b >> 4]; | 
| 269 | 0 |  |  |  |  |  | *write++ = base64_encode[(b & 0x0f) << 2 | c >> 6]; | 
| 270 | 0 |  |  |  |  |  | *write++ = base64_encode[c & 0x3f]; | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | 
| 273 | 0 | 0 |  |  |  |  | if (extra > 0) { | 
| 274 | 0 |  |  |  |  |  | a = *read++; | 
| 275 | 0 | 0 |  |  |  |  | b = (extra > 1) ? *read++ : 0; | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 0 |  |  |  |  |  | *write++ = base64_encode[a >> 2]; | 
| 278 | 0 |  |  |  |  |  | *write++ = base64_encode[(a & 0x03) << 4 | b >> 4]; | 
| 279 | 0 | 0 |  |  |  |  | *write++ = (extra > 1) ? base64_encode[(b & 0x0f) << 2] : '='; | 
| 280 | 0 |  |  |  |  |  | *write++ = '='; | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 | 0 |  |  |  |  |  | buf->size = ((char *)write) - buf->ptr; | 
| 284 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 0 |  |  |  |  |  | return 0; | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | /* The inverse of base64_encode */ | 
| 290 |  |  |  |  |  |  | static const int8_t base64_decode[] = { | 
| 291 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 292 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 293 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, | 
| 294 |  |  |  |  |  |  | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1, | 
| 295 |  |  |  |  |  |  | -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, | 
| 296 |  |  |  |  |  |  | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | 
| 297 |  |  |  |  |  |  | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | 
| 298 |  |  |  |  |  |  | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, | 
| 299 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 300 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 301 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 302 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 303 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 304 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 305 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 306 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | 
| 307 |  |  |  |  |  |  | }; | 
| 308 |  |  |  |  |  |  |  | 
| 309 | 0 |  |  |  |  |  | int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len) | 
| 310 |  |  |  |  |  |  | { | 
| 311 |  |  |  |  |  |  | size_t i; | 
| 312 |  |  |  |  |  |  | int8_t a, b, c, d; | 
| 313 | 0 |  |  |  |  |  | size_t orig_size = buf->size, new_size; | 
| 314 |  |  |  |  |  |  |  | 
| 315 | 0 | 0 |  |  |  |  | if (len % 4) { | 
| 316 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid base64 input"); | 
| 317 | 0 |  |  |  |  |  | return -1; | 
| 318 |  |  |  |  |  |  | } | 
| 319 |  |  |  |  |  |  |  | 
| 320 | 0 | 0 |  |  |  |  | assert(len % 4 == 0); | 
| 321 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 322 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 323 | 0 | 0 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 0 | 0 |  |  |  |  | for (i = 0; i < len; i += 4) { | 
| 326 | 0 | 0 |  |  |  |  | if ((a = base64_decode[(unsigned char)base64[i]]) < 0 || | 
|  |  | 0 |  |  |  |  |  | 
| 327 | 0 | 0 |  |  |  |  | (b = base64_decode[(unsigned char)base64[i+1]]) < 0 || | 
| 328 | 0 | 0 |  |  |  |  | (c = base64_decode[(unsigned char)base64[i+2]]) < 0 || | 
| 329 | 0 |  |  |  |  |  | (d = base64_decode[(unsigned char)base64[i+3]]) < 0) { | 
| 330 | 0 |  |  |  |  |  | buf->size = orig_size; | 
| 331 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 332 |  |  |  |  |  |  |  | 
| 333 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid base64 input"); | 
| 334 | 0 |  |  |  |  |  | return -1; | 
| 335 |  |  |  |  |  |  | } | 
| 336 |  |  |  |  |  |  |  | 
| 337 | 0 |  |  |  |  |  | buf->ptr[buf->size++] = ((a << 2) | (b & 0x30) >> 4); | 
| 338 | 0 |  |  |  |  |  | buf->ptr[buf->size++] = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); | 
| 339 | 0 |  |  |  |  |  | buf->ptr[buf->size++] = (c & 0x03) << 6 | (d & 0x3f); | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 343 | 0 |  |  |  |  |  | return 0; | 
| 344 |  |  |  |  |  |  | } | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  | static const char base85_encode[] = | 
| 347 |  |  |  |  |  |  | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; | 
| 348 |  |  |  |  |  |  |  | 
| 349 | 2 |  |  |  |  |  | int git_buf_encode_base85(git_buf *buf, const char *data, size_t len) | 
| 350 |  |  |  |  |  |  | { | 
| 351 | 2 |  |  |  |  |  | size_t blocks = (len / 4) + !!(len % 4), alloclen; | 
| 352 |  |  |  |  |  |  |  | 
| 353 | 2 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 5); | 
|  |  | 50 |  |  |  |  |  | 
| 354 | 2 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size); | 
|  |  | 50 |  |  |  |  |  | 
| 355 | 2 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 2 | 50 |  |  |  |  | ENSURE_SIZE(buf, alloclen); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 358 |  |  |  |  |  |  |  | 
| 359 | 10 | 100 |  |  |  |  | while (len) { | 
| 360 | 8 |  |  |  |  |  | uint32_t acc = 0; | 
| 361 |  |  |  |  |  |  | char b85[5]; | 
| 362 |  |  |  |  |  |  | int i; | 
| 363 |  |  |  |  |  |  |  | 
| 364 | 38 | 100 |  |  |  |  | for (i = 24; i >= 0; i -= 8) { | 
| 365 | 32 |  |  |  |  |  | uint8_t ch = *data++; | 
| 366 | 32 |  |  |  |  |  | acc |= ch << i; | 
| 367 |  |  |  |  |  |  |  | 
| 368 | 32 | 100 |  |  |  |  | if (--len == 0) | 
| 369 | 2 |  |  |  |  |  | break; | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  |  | 
| 372 | 48 | 100 |  |  |  |  | for (i = 4; i >= 0; i--) { | 
| 373 | 40 |  |  |  |  |  | int val = acc % 85; | 
| 374 | 40 |  |  |  |  |  | acc /= 85; | 
| 375 |  |  |  |  |  |  |  | 
| 376 | 40 |  |  |  |  |  | b85[i] = base85_encode[val]; | 
| 377 |  |  |  |  |  |  | } | 
| 378 |  |  |  |  |  |  |  | 
| 379 | 48 | 100 |  |  |  |  | for (i = 0; i < 5; i++) | 
| 380 | 40 |  |  |  |  |  | buf->ptr[buf->size++] = b85[i]; | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 | 2 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 384 |  |  |  |  |  |  |  | 
| 385 | 2 |  |  |  |  |  | return 0; | 
| 386 |  |  |  |  |  |  | } | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  | /* The inverse of base85_encode */ | 
| 389 |  |  |  |  |  |  | static const int8_t base85_decode[] = { | 
| 390 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 391 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 392 |  |  |  |  |  |  | -1, 63, -1, 64, 65, 66, 67, -1, 68, 69, 70, 71, -1, 72, -1, -1, | 
| 393 |  |  |  |  |  |  | 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, -1, 73, 74, 75, 76, 77, | 
| 394 |  |  |  |  |  |  | 78, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, | 
| 395 |  |  |  |  |  |  | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, -1, -1, 79, 80, | 
| 396 |  |  |  |  |  |  | 81, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, | 
| 397 |  |  |  |  |  |  | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 82, 83, 84, 85, -1, | 
| 398 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 399 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 400 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 401 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 402 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 403 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 404 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 
| 405 |  |  |  |  |  |  | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | 
| 406 |  |  |  |  |  |  | }; | 
| 407 |  |  |  |  |  |  |  | 
| 408 | 0 |  |  |  |  |  | int git_buf_decode_base85( | 
| 409 |  |  |  |  |  |  | git_buf *buf, | 
| 410 |  |  |  |  |  |  | const char *base85, | 
| 411 |  |  |  |  |  |  | size_t base85_len, | 
| 412 |  |  |  |  |  |  | size_t output_len) | 
| 413 |  |  |  |  |  |  | { | 
| 414 | 0 |  |  |  |  |  | size_t orig_size = buf->size, new_size; | 
| 415 |  |  |  |  |  |  |  | 
| 416 | 0 | 0 |  |  |  |  | if (base85_len % 5 || | 
|  |  | 0 |  |  |  |  |  | 
| 417 | 0 |  |  |  |  |  | output_len > base85_len * 4 / 5) { | 
| 418 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid base85 input"); | 
| 419 | 0 |  |  |  |  |  | return -1; | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  |  | 
| 422 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, output_len, buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 423 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 424 | 0 | 0 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 425 |  |  |  |  |  |  |  | 
| 426 | 0 | 0 |  |  |  |  | while (output_len) { | 
| 427 | 0 |  |  |  |  |  | unsigned acc = 0; | 
| 428 | 0 |  |  |  |  |  | int de, cnt = 4; | 
| 429 |  |  |  |  |  |  | unsigned char ch; | 
| 430 |  |  |  |  |  |  | do { | 
| 431 | 0 |  |  |  |  |  | ch = *base85++; | 
| 432 | 0 |  |  |  |  |  | de = base85_decode[ch]; | 
| 433 | 0 | 0 |  |  |  |  | if (--de < 0) | 
| 434 | 0 |  |  |  |  |  | goto on_error; | 
| 435 |  |  |  |  |  |  |  | 
| 436 | 0 |  |  |  |  |  | acc = acc * 85 + de; | 
| 437 | 0 | 0 |  |  |  |  | } while (--cnt); | 
| 438 | 0 |  |  |  |  |  | ch = *base85++; | 
| 439 | 0 |  |  |  |  |  | de = base85_decode[ch]; | 
| 440 | 0 | 0 |  |  |  |  | if (--de < 0) | 
| 441 | 0 |  |  |  |  |  | goto on_error; | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | /* Detect overflow. */ | 
| 444 | 0 | 0 |  |  |  |  | if (0xffffffff / 85 < acc || | 
|  |  | 0 |  |  |  |  |  | 
| 445 | 0 |  |  |  |  |  | 0xffffffff - de < (acc *= 85)) | 
| 446 |  |  |  |  |  |  | goto on_error; | 
| 447 |  |  |  |  |  |  |  | 
| 448 | 0 |  |  |  |  |  | acc += de; | 
| 449 |  |  |  |  |  |  |  | 
| 450 | 0 | 0 |  |  |  |  | cnt = (output_len < 4) ? (int)output_len : 4; | 
| 451 | 0 |  |  |  |  |  | output_len -= cnt; | 
| 452 |  |  |  |  |  |  | do { | 
| 453 | 0 |  |  |  |  |  | acc = (acc << 8) | (acc >> 24); | 
| 454 | 0 |  |  |  |  |  | buf->ptr[buf->size++] = acc; | 
| 455 | 0 | 0 |  |  |  |  | } while (--cnt); | 
| 456 |  |  |  |  |  |  | } | 
| 457 |  |  |  |  |  |  |  | 
| 458 | 0 |  |  |  |  |  | buf->ptr[buf->size] = 0; | 
| 459 |  |  |  |  |  |  |  | 
| 460 | 0 |  |  |  |  |  | return 0; | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | on_error: | 
| 463 | 0 |  |  |  |  |  | buf->size = orig_size; | 
| 464 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 465 |  |  |  |  |  |  |  | 
| 466 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid base85 input"); | 
| 467 | 0 |  |  |  |  |  | return -1; | 
| 468 |  |  |  |  |  |  | } | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | #define HEX_DECODE(c) ((c | 32) % 39 - 9) | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 0 |  |  |  |  |  | int git_buf_decode_percent( | 
| 473 |  |  |  |  |  |  | git_buf *buf, | 
| 474 |  |  |  |  |  |  | const char *str, | 
| 475 |  |  |  |  |  |  | size_t str_len) | 
| 476 |  |  |  |  |  |  | { | 
| 477 |  |  |  |  |  |  | size_t str_pos, new_size; | 
| 478 |  |  |  |  |  |  |  | 
| 479 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, str_len); | 
|  |  | 0 |  |  |  |  |  | 
| 480 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 481 | 0 | 0 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 482 |  |  |  |  |  |  |  | 
| 483 | 0 | 0 |  |  |  |  | for (str_pos = 0; str_pos < str_len; buf->size++, str_pos++) { | 
| 484 | 0 | 0 |  |  |  |  | if (str[str_pos] == '%' && | 
|  |  | 0 |  |  |  |  |  | 
| 485 | 0 | 0 |  |  |  |  | str_len > str_pos + 2 && | 
| 486 | 0 | 0 |  |  |  |  | isxdigit(str[str_pos + 1]) && | 
| 487 | 0 |  |  |  |  |  | isxdigit(str[str_pos + 2])) { | 
| 488 | 0 |  |  |  |  |  | buf->ptr[buf->size] = (HEX_DECODE(str[str_pos + 1]) << 4) + | 
| 489 | 0 |  |  |  |  |  | HEX_DECODE(str[str_pos + 2]); | 
| 490 | 0 |  |  |  |  |  | str_pos += 2; | 
| 491 |  |  |  |  |  |  | } else { | 
| 492 | 0 |  |  |  |  |  | buf->ptr[buf->size] = str[str_pos]; | 
| 493 |  |  |  |  |  |  | } | 
| 494 |  |  |  |  |  |  | } | 
| 495 |  |  |  |  |  |  |  | 
| 496 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 497 | 0 |  |  |  |  |  | return 0; | 
| 498 |  |  |  |  |  |  | } | 
| 499 |  |  |  |  |  |  |  | 
| 500 | 5901 |  |  |  |  |  | int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) | 
| 501 |  |  |  |  |  |  | { | 
| 502 |  |  |  |  |  |  | size_t expected_size, new_size; | 
| 503 |  |  |  |  |  |  | int len; | 
| 504 |  |  |  |  |  |  |  | 
| 505 | 5901 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_MULTIPLY(&expected_size, strlen(format), 2); | 
|  |  | 50 |  |  |  |  |  | 
| 506 | 5901 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&expected_size, expected_size, buf->size); | 
|  |  | 50 |  |  |  |  |  | 
| 507 | 5901 | 50 |  |  |  |  | ENSURE_SIZE(buf, expected_size); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | while (1) { | 
| 510 |  |  |  |  |  |  | va_list args; | 
| 511 | 6250 |  |  |  |  |  | va_copy(args, ap); | 
| 512 |  |  |  |  |  |  |  | 
| 513 | 6250 |  |  |  |  |  | len = p_vsnprintf( | 
| 514 |  |  |  |  |  |  | buf->ptr + buf->size, | 
| 515 |  |  |  |  |  |  | buf->asize - buf->size, | 
| 516 |  |  |  |  |  |  | format, args | 
| 517 |  |  |  |  |  |  | ); | 
| 518 |  |  |  |  |  |  |  | 
| 519 | 6250 |  |  |  |  |  | va_end(args); | 
| 520 |  |  |  |  |  |  |  | 
| 521 | 6250 | 50 |  |  |  |  | if (len < 0) { | 
| 522 | 0 |  |  |  |  |  | git__free(buf->ptr); | 
| 523 | 0 |  |  |  |  |  | buf->ptr = git_buf__oom; | 
| 524 | 5901 |  |  |  |  |  | return -1; | 
| 525 |  |  |  |  |  |  | } | 
| 526 |  |  |  |  |  |  |  | 
| 527 | 6250 | 100 |  |  |  |  | if ((size_t)len + 1 <= buf->asize - buf->size) { | 
| 528 | 5901 |  |  |  |  |  | buf->size += len; | 
| 529 | 5901 |  |  |  |  |  | break; | 
| 530 |  |  |  |  |  |  | } | 
| 531 |  |  |  |  |  |  |  | 
| 532 | 349 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, buf->size, len); | 
|  |  | 50 |  |  |  |  |  | 
| 533 | 349 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, new_size, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 534 | 349 | 50 |  |  |  |  | ENSURE_SIZE(buf, new_size); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 535 | 349 |  |  |  |  |  | } | 
| 536 |  |  |  |  |  |  |  | 
| 537 | 5901 |  |  |  |  |  | return 0; | 
| 538 |  |  |  |  |  |  | } | 
| 539 |  |  |  |  |  |  |  | 
| 540 | 1394 |  |  |  |  |  | int git_buf_printf(git_buf *buf, const char *format, ...) | 
| 541 |  |  |  |  |  |  | { | 
| 542 |  |  |  |  |  |  | int r; | 
| 543 |  |  |  |  |  |  | va_list ap; | 
| 544 |  |  |  |  |  |  |  | 
| 545 | 1394 |  |  |  |  |  | va_start(ap, format); | 
| 546 | 1394 |  |  |  |  |  | r = git_buf_vprintf(buf, format, ap); | 
| 547 | 1394 |  |  |  |  |  | va_end(ap); | 
| 548 |  |  |  |  |  |  |  | 
| 549 | 1394 |  |  |  |  |  | return r; | 
| 550 |  |  |  |  |  |  | } | 
| 551 |  |  |  |  |  |  |  | 
| 552 | 1280 |  |  |  |  |  | void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf) | 
| 553 |  |  |  |  |  |  | { | 
| 554 |  |  |  |  |  |  | size_t copylen; | 
| 555 |  |  |  |  |  |  |  | 
| 556 | 1280 | 50 |  |  |  |  | assert(data && datasize && buf); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 557 |  |  |  |  |  |  |  | 
| 558 | 1280 |  |  |  |  |  | data[0] = '\0'; | 
| 559 |  |  |  |  |  |  |  | 
| 560 | 1280 | 50 |  |  |  |  | if (buf->size == 0 || buf->asize <= 0) | 
|  |  | 50 |  |  |  |  |  | 
| 561 | 0 |  |  |  |  |  | return; | 
| 562 |  |  |  |  |  |  |  | 
| 563 | 1280 |  |  |  |  |  | copylen = buf->size; | 
| 564 | 1280 | 50 |  |  |  |  | if (copylen > datasize - 1) | 
| 565 | 0 |  |  |  |  |  | copylen = datasize - 1; | 
| 566 | 1280 |  |  |  |  |  | memmove(data, buf->ptr, copylen); | 
| 567 | 1280 |  |  |  |  |  | data[copylen] = '\0'; | 
| 568 |  |  |  |  |  |  | } | 
| 569 |  |  |  |  |  |  |  | 
| 570 | 0 |  |  |  |  |  | void git_buf_consume_bytes(git_buf *buf, size_t len) | 
| 571 |  |  |  |  |  |  | { | 
| 572 | 0 |  |  |  |  |  | git_buf_consume(buf, buf->ptr + len); | 
| 573 | 0 |  |  |  |  |  | } | 
| 574 |  |  |  |  |  |  |  | 
| 575 | 19 |  |  |  |  |  | void git_buf_consume(git_buf *buf, const char *end) | 
| 576 |  |  |  |  |  |  | { | 
| 577 | 19 | 50 |  |  |  |  | if (end > buf->ptr && end <= buf->ptr + buf->size) { | 
|  |  | 50 |  |  |  |  |  | 
| 578 | 19 |  |  |  |  |  | size_t consumed = end - buf->ptr; | 
| 579 | 19 |  |  |  |  |  | memmove(buf->ptr, end, buf->size - consumed); | 
| 580 | 19 |  |  |  |  |  | buf->size -= consumed; | 
| 581 | 19 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 582 |  |  |  |  |  |  | } | 
| 583 | 19 |  |  |  |  |  | } | 
| 584 |  |  |  |  |  |  |  | 
| 585 | 5228 |  |  |  |  |  | void git_buf_truncate(git_buf *buf, size_t len) | 
| 586 |  |  |  |  |  |  | { | 
| 587 | 5228 | 100 |  |  |  |  | if (len >= buf->size) | 
| 588 | 1818 |  |  |  |  |  | return; | 
| 589 |  |  |  |  |  |  |  | 
| 590 | 3410 |  |  |  |  |  | buf->size = len; | 
| 591 | 3410 | 50 |  |  |  |  | if (buf->size < buf->asize) | 
| 592 | 3410 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 593 |  |  |  |  |  |  | } | 
| 594 |  |  |  |  |  |  |  | 
| 595 | 5 |  |  |  |  |  | void git_buf_shorten(git_buf *buf, size_t amount) | 
| 596 |  |  |  |  |  |  | { | 
| 597 | 5 | 50 |  |  |  |  | if (buf->size > amount) | 
| 598 | 5 |  |  |  |  |  | git_buf_truncate(buf, buf->size - amount); | 
| 599 |  |  |  |  |  |  | else | 
| 600 | 0 |  |  |  |  |  | git_buf_clear(buf); | 
| 601 | 5 |  |  |  |  |  | } | 
| 602 |  |  |  |  |  |  |  | 
| 603 | 176 |  |  |  |  |  | void git_buf_rtruncate_at_char(git_buf *buf, char separator) | 
| 604 |  |  |  |  |  |  | { | 
| 605 | 176 |  |  |  |  |  | ssize_t idx = git_buf_rfind_next(buf, separator); | 
| 606 | 176 |  |  |  |  |  | git_buf_truncate(buf, idx < 0 ? 0 : (size_t)idx); | 
| 607 | 176 |  |  |  |  |  | } | 
| 608 |  |  |  |  |  |  |  | 
| 609 | 2328 |  |  |  |  |  | void git_buf_swap(git_buf *buf_a, git_buf *buf_b) | 
| 610 |  |  |  |  |  |  | { | 
| 611 | 2328 |  |  |  |  |  | git_buf t = *buf_a; | 
| 612 | 2328 |  |  |  |  |  | *buf_a = *buf_b; | 
| 613 | 2328 |  |  |  |  |  | *buf_b = t; | 
| 614 | 2328 |  |  |  |  |  | } | 
| 615 |  |  |  |  |  |  |  | 
| 616 | 2510 |  |  |  |  |  | char *git_buf_detach(git_buf *buf) | 
| 617 |  |  |  |  |  |  | { | 
| 618 | 2510 |  |  |  |  |  | char *data = buf->ptr; | 
| 619 |  |  |  |  |  |  |  | 
| 620 | 2510 | 50 |  |  |  |  | if (buf->asize == 0 || buf->ptr == git_buf__oom) | 
|  |  | 50 |  |  |  |  |  | 
| 621 | 0 |  |  |  |  |  | return NULL; | 
| 622 |  |  |  |  |  |  |  | 
| 623 | 2510 |  |  |  |  |  | git_buf_init(buf, 0); | 
| 624 |  |  |  |  |  |  |  | 
| 625 | 2510 |  |  |  |  |  | return data; | 
| 626 |  |  |  |  |  |  | } | 
| 627 |  |  |  |  |  |  |  | 
| 628 | 48 |  |  |  |  |  | int git_buf_attach(git_buf *buf, char *ptr, size_t asize) | 
| 629 |  |  |  |  |  |  | { | 
| 630 | 48 |  |  |  |  |  | git_buf_dispose(buf); | 
| 631 |  |  |  |  |  |  |  | 
| 632 | 48 | 100 |  |  |  |  | if (ptr) { | 
| 633 | 8 |  |  |  |  |  | buf->ptr = ptr; | 
| 634 | 8 |  |  |  |  |  | buf->size = strlen(ptr); | 
| 635 | 8 | 100 |  |  |  |  | if (asize) | 
| 636 | 2 | 50 |  |  |  |  | buf->asize = (asize < buf->size) ? buf->size + 1 : asize; | 
| 637 |  |  |  |  |  |  | else /* pass 0 to fall back on strlen + 1 */ | 
| 638 | 6 |  |  |  |  |  | buf->asize = buf->size + 1; | 
| 639 |  |  |  |  |  |  | } | 
| 640 |  |  |  |  |  |  |  | 
| 641 | 48 | 50 |  |  |  |  | ENSURE_SIZE(buf, asize); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 642 | 48 |  |  |  |  |  | return 0; | 
| 643 |  |  |  |  |  |  | } | 
| 644 |  |  |  |  |  |  |  | 
| 645 | 107 |  |  |  |  |  | void git_buf_attach_notowned(git_buf *buf, const char *ptr, size_t size) | 
| 646 |  |  |  |  |  |  | { | 
| 647 | 107 | 50 |  |  |  |  | if (git_buf_is_allocated(buf)) | 
| 648 | 0 |  |  |  |  |  | git_buf_dispose(buf); | 
| 649 |  |  |  |  |  |  |  | 
| 650 | 107 | 100 |  |  |  |  | if (!size) { | 
| 651 | 29 |  |  |  |  |  | git_buf_init(buf, 0); | 
| 652 |  |  |  |  |  |  | } else { | 
| 653 | 78 |  |  |  |  |  | buf->ptr = (char *)ptr; | 
| 654 | 78 |  |  |  |  |  | buf->asize = 0; | 
| 655 | 78 |  |  |  |  |  | buf->size = size; | 
| 656 |  |  |  |  |  |  | } | 
| 657 | 107 |  |  |  |  |  | } | 
| 658 |  |  |  |  |  |  |  | 
| 659 | 0 |  |  |  |  |  | int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...) | 
| 660 |  |  |  |  |  |  | { | 
| 661 |  |  |  |  |  |  | va_list ap; | 
| 662 |  |  |  |  |  |  | int i; | 
| 663 | 0 |  |  |  |  |  | size_t total_size = 0, original_size = buf->size; | 
| 664 | 0 |  |  |  |  |  | char *out, *original = buf->ptr; | 
| 665 |  |  |  |  |  |  |  | 
| 666 | 0 | 0 |  |  |  |  | if (buf->size > 0 && buf->ptr[buf->size - 1] != separator) | 
|  |  | 0 |  |  |  |  |  | 
| 667 | 0 |  |  |  |  |  | ++total_size; /* space for initial separator */ | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | /* Make two passes to avoid multiple reallocation */ | 
| 670 |  |  |  |  |  |  |  | 
| 671 | 0 |  |  |  |  |  | va_start(ap, nbuf); | 
| 672 | 0 | 0 |  |  |  |  | for (i = 0; i < nbuf; ++i) { | 
| 673 |  |  |  |  |  |  | const char* segment; | 
| 674 |  |  |  |  |  |  | size_t segment_len; | 
| 675 |  |  |  |  |  |  |  | 
| 676 | 0 | 0 |  |  |  |  | segment = va_arg(ap, const char *); | 
| 677 | 0 | 0 |  |  |  |  | if (!segment) | 
| 678 | 0 |  |  |  |  |  | continue; | 
| 679 |  |  |  |  |  |  |  | 
| 680 | 0 |  |  |  |  |  | segment_len = strlen(segment); | 
| 681 |  |  |  |  |  |  |  | 
| 682 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, segment_len); | 
|  |  | 0 |  |  |  |  |  | 
| 683 |  |  |  |  |  |  |  | 
| 684 | 0 | 0 |  |  |  |  | if (segment_len == 0 || segment[segment_len - 1] != separator) | 
|  |  | 0 |  |  |  |  |  | 
| 685 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | } | 
| 687 | 0 |  |  |  |  |  | va_end(ap); | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | /* expand buffer if needed */ | 
| 690 | 0 | 0 |  |  |  |  | if (total_size == 0) | 
| 691 | 0 |  |  |  |  |  | return 0; | 
| 692 |  |  |  |  |  |  |  | 
| 693 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&total_size, total_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 694 | 0 | 0 |  |  |  |  | if (git_buf_grow_by(buf, total_size) < 0) | 
| 695 | 0 |  |  |  |  |  | return -1; | 
| 696 |  |  |  |  |  |  |  | 
| 697 | 0 |  |  |  |  |  | out = buf->ptr + buf->size; | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | /* append separator to existing buf if needed */ | 
| 700 | 0 | 0 |  |  |  |  | if (buf->size > 0 && out[-1] != separator) | 
|  |  | 0 |  |  |  |  |  | 
| 701 | 0 |  |  |  |  |  | *out++ = separator; | 
| 702 |  |  |  |  |  |  |  | 
| 703 | 0 |  |  |  |  |  | va_start(ap, nbuf); | 
| 704 | 0 | 0 |  |  |  |  | for (i = 0; i < nbuf; ++i) { | 
| 705 |  |  |  |  |  |  | const char* segment; | 
| 706 |  |  |  |  |  |  | size_t segment_len; | 
| 707 |  |  |  |  |  |  |  | 
| 708 | 0 | 0 |  |  |  |  | segment = va_arg(ap, const char *); | 
| 709 | 0 | 0 |  |  |  |  | if (!segment) | 
| 710 | 0 |  |  |  |  |  | continue; | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | /* deal with join that references buffer's original content */ | 
| 713 | 0 | 0 |  |  |  |  | if (segment >= original && segment < original + original_size) { | 
|  |  | 0 |  |  |  |  |  | 
| 714 | 0 |  |  |  |  |  | size_t offset = (segment - original); | 
| 715 | 0 |  |  |  |  |  | segment = buf->ptr + offset; | 
| 716 | 0 |  |  |  |  |  | segment_len = original_size - offset; | 
| 717 |  |  |  |  |  |  | } else { | 
| 718 | 0 |  |  |  |  |  | segment_len = strlen(segment); | 
| 719 |  |  |  |  |  |  | } | 
| 720 |  |  |  |  |  |  |  | 
| 721 |  |  |  |  |  |  | /* skip leading separators */ | 
| 722 | 0 | 0 |  |  |  |  | if (out > buf->ptr && out[-1] == separator) | 
|  |  | 0 |  |  |  |  |  | 
| 723 | 0 | 0 |  |  |  |  | while (segment_len > 0 && *segment == separator) { | 
|  |  | 0 |  |  |  |  |  | 
| 724 | 0 |  |  |  |  |  | segment++; | 
| 725 | 0 |  |  |  |  |  | segment_len--; | 
| 726 |  |  |  |  |  |  | } | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | /* copy over next buffer */ | 
| 729 | 0 | 0 |  |  |  |  | if (segment_len > 0) { | 
| 730 | 0 |  |  |  |  |  | memmove(out, segment, segment_len); | 
| 731 | 0 |  |  |  |  |  | out += segment_len; | 
| 732 |  |  |  |  |  |  | } | 
| 733 |  |  |  |  |  |  |  | 
| 734 |  |  |  |  |  |  | /* append trailing separator (except for last item) */ | 
| 735 | 0 | 0 |  |  |  |  | if (i < nbuf - 1 && out > buf->ptr && out[-1] != separator) | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 736 | 0 |  |  |  |  |  | *out++ = separator; | 
| 737 |  |  |  |  |  |  | } | 
| 738 | 0 |  |  |  |  |  | va_end(ap); | 
| 739 |  |  |  |  |  |  |  | 
| 740 |  |  |  |  |  |  | /* set size based on num characters actually written */ | 
| 741 | 0 |  |  |  |  |  | buf->size = out - buf->ptr; | 
| 742 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 743 |  |  |  |  |  |  |  | 
| 744 | 0 |  |  |  |  |  | return 0; | 
| 745 |  |  |  |  |  |  | } | 
| 746 |  |  |  |  |  |  |  | 
| 747 | 14948 |  |  |  |  |  | int git_buf_join( | 
| 748 |  |  |  |  |  |  | git_buf *buf, | 
| 749 |  |  |  |  |  |  | char separator, | 
| 750 |  |  |  |  |  |  | const char *str_a, | 
| 751 |  |  |  |  |  |  | const char *str_b) | 
| 752 |  |  |  |  |  |  | { | 
| 753 | 14948 | 100 |  |  |  |  | size_t strlen_a = str_a ? strlen(str_a) : 0; | 
| 754 | 14948 |  |  |  |  |  | size_t strlen_b = strlen(str_b); | 
| 755 |  |  |  |  |  |  | size_t alloc_len; | 
| 756 | 14948 |  |  |  |  |  | int need_sep = 0; | 
| 757 | 14948 |  |  |  |  |  | ssize_t offset_a = -1; | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  | /* not safe to have str_b point internally to the buffer */ | 
| 760 | 14948 | 100 |  |  |  |  | assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size); | 
|  |  | 50 |  |  |  |  |  | 
| 761 |  |  |  |  |  |  |  | 
| 762 |  |  |  |  |  |  | /* figure out if we need to insert a separator */ | 
| 763 | 14948 | 50 |  |  |  |  | if (separator && strlen_a) { | 
|  |  | 100 |  |  |  |  |  | 
| 764 | 13653 | 100 |  |  |  |  | while (*str_b == separator) { str_b++; strlen_b--; } | 
| 765 | 13648 | 100 |  |  |  |  | if (str_a[strlen_a - 1] != separator) | 
| 766 | 2822 |  |  |  |  |  | need_sep = 1; | 
| 767 |  |  |  |  |  |  | } | 
| 768 |  |  |  |  |  |  |  | 
| 769 |  |  |  |  |  |  | /* str_a could be part of the buffer */ | 
| 770 | 14948 | 100 |  |  |  |  | if (str_a >= buf->ptr && str_a < buf->ptr + buf->size) | 
|  |  | 100 |  |  |  |  |  | 
| 771 | 3254 |  |  |  |  |  | offset_a = str_a - buf->ptr; | 
| 772 |  |  |  |  |  |  |  | 
| 773 | 14948 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b); | 
|  |  | 50 |  |  |  |  |  | 
| 774 | 14948 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep); | 
|  |  | 50 |  |  |  |  |  | 
| 775 | 14948 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 776 | 14948 | 50 |  |  |  |  | ENSURE_SIZE(buf, alloc_len); | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | /* fix up internal pointers */ | 
| 779 | 14948 | 100 |  |  |  |  | if (offset_a >= 0) | 
| 780 | 3254 |  |  |  |  |  | str_a = buf->ptr + offset_a; | 
| 781 |  |  |  |  |  |  |  | 
| 782 |  |  |  |  |  |  | /* do the actual copying */ | 
| 783 | 14948 | 100 |  |  |  |  | if (offset_a != 0 && str_a) | 
|  |  | 100 |  |  |  |  |  | 
| 784 | 11693 |  |  |  |  |  | memmove(buf->ptr, str_a, strlen_a); | 
| 785 | 14948 | 100 |  |  |  |  | if (need_sep) | 
| 786 | 2822 |  |  |  |  |  | buf->ptr[strlen_a] = separator; | 
| 787 | 14948 |  |  |  |  |  | memcpy(buf->ptr + strlen_a + need_sep, str_b, strlen_b); | 
| 788 |  |  |  |  |  |  |  | 
| 789 | 14948 |  |  |  |  |  | buf->size = strlen_a + strlen_b + need_sep; | 
| 790 | 14948 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 791 |  |  |  |  |  |  |  | 
| 792 | 14948 |  |  |  |  |  | return 0; | 
| 793 |  |  |  |  |  |  | } | 
| 794 |  |  |  |  |  |  |  | 
| 795 | 247 |  |  |  |  |  | int git_buf_join3( | 
| 796 |  |  |  |  |  |  | git_buf *buf, | 
| 797 |  |  |  |  |  |  | char separator, | 
| 798 |  |  |  |  |  |  | const char *str_a, | 
| 799 |  |  |  |  |  |  | const char *str_b, | 
| 800 |  |  |  |  |  |  | const char *str_c) | 
| 801 |  |  |  |  |  |  | { | 
| 802 | 247 |  |  |  |  |  | size_t len_a = strlen(str_a), | 
| 803 | 247 |  |  |  |  |  | len_b = strlen(str_b), | 
| 804 | 247 |  |  |  |  |  | len_c = strlen(str_c), | 
| 805 |  |  |  |  |  |  | len_total; | 
| 806 | 247 |  |  |  |  |  | int sep_a = 0, sep_b = 0; | 
| 807 |  |  |  |  |  |  | char *tgt; | 
| 808 |  |  |  |  |  |  |  | 
| 809 |  |  |  |  |  |  | /* for this function, disallow pointers into the existing buffer */ | 
| 810 | 247 | 50 |  |  |  |  | assert(str_a < buf->ptr || str_a >= buf->ptr + buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 811 | 247 | 50 |  |  |  |  | assert(str_b < buf->ptr || str_b >= buf->ptr + buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 812 | 247 | 50 |  |  |  |  | assert(str_c < buf->ptr || str_c >= buf->ptr + buf->size); | 
|  |  | 0 |  |  |  |  |  | 
| 813 |  |  |  |  |  |  |  | 
| 814 | 247 | 50 |  |  |  |  | if (separator) { | 
| 815 | 247 | 50 |  |  |  |  | if (len_a > 0) { | 
| 816 | 247 | 50 |  |  |  |  | while (*str_b == separator) { str_b++; len_b--; } | 
| 817 | 247 |  |  |  |  |  | sep_a = (str_a[len_a - 1] != separator); | 
| 818 |  |  |  |  |  |  | } | 
| 819 | 247 | 50 |  |  |  |  | if (len_a > 0 || len_b > 0) | 
|  |  | 0 |  |  |  |  |  | 
| 820 | 247 | 50 |  |  |  |  | while (*str_c == separator) { str_c++; len_c--; } | 
| 821 | 247 | 100 |  |  |  |  | if (len_b > 0) | 
| 822 | 243 |  |  |  |  |  | sep_b = (str_b[len_b - 1] != separator); | 
| 823 |  |  |  |  |  |  | } | 
| 824 |  |  |  |  |  |  |  | 
| 825 | 247 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_a, sep_a); | 
|  |  | 50 |  |  |  |  |  | 
| 826 | 247 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_b); | 
|  |  | 50 |  |  |  |  |  | 
| 827 | 247 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b); | 
|  |  | 50 |  |  |  |  |  | 
| 828 | 247 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, len_c); | 
|  |  | 50 |  |  |  |  |  | 
| 829 | 247 | 50 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&len_total, len_total, 1); | 
|  |  | 50 |  |  |  |  |  | 
| 830 | 247 | 50 |  |  |  |  | ENSURE_SIZE(buf, len_total); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 831 |  |  |  |  |  |  |  | 
| 832 | 247 |  |  |  |  |  | tgt = buf->ptr; | 
| 833 |  |  |  |  |  |  |  | 
| 834 | 247 | 50 |  |  |  |  | if (len_a) { | 
| 835 | 247 |  |  |  |  |  | memcpy(tgt, str_a, len_a); | 
| 836 | 247 |  |  |  |  |  | tgt += len_a; | 
| 837 |  |  |  |  |  |  | } | 
| 838 | 247 | 50 |  |  |  |  | if (sep_a) | 
| 839 | 0 |  |  |  |  |  | *tgt++ = separator; | 
| 840 | 247 | 100 |  |  |  |  | if (len_b) { | 
| 841 | 243 |  |  |  |  |  | memcpy(tgt, str_b, len_b); | 
| 842 | 243 |  |  |  |  |  | tgt += len_b; | 
| 843 |  |  |  |  |  |  | } | 
| 844 | 247 | 50 |  |  |  |  | if (sep_b) | 
| 845 | 0 |  |  |  |  |  | *tgt++ = separator; | 
| 846 | 247 | 50 |  |  |  |  | if (len_c) | 
| 847 | 247 |  |  |  |  |  | memcpy(tgt, str_c, len_c); | 
| 848 |  |  |  |  |  |  |  | 
| 849 | 247 |  |  |  |  |  | buf->size = len_a + sep_a + len_b + sep_b + len_c; | 
| 850 | 247 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 851 |  |  |  |  |  |  |  | 
| 852 | 247 |  |  |  |  |  | return 0; | 
| 853 |  |  |  |  |  |  | } | 
| 854 |  |  |  |  |  |  |  | 
| 855 | 792 |  |  |  |  |  | void git_buf_rtrim(git_buf *buf) | 
| 856 |  |  |  |  |  |  | { | 
| 857 | 1462 | 50 |  |  |  |  | while (buf->size > 0) { | 
| 858 | 1462 | 100 |  |  |  |  | if (!git__isspace(buf->ptr[buf->size - 1])) | 
| 859 | 792 |  |  |  |  |  | break; | 
| 860 |  |  |  |  |  |  |  | 
| 861 | 670 |  |  |  |  |  | buf->size--; | 
| 862 |  |  |  |  |  |  | } | 
| 863 |  |  |  |  |  |  |  | 
| 864 | 792 | 50 |  |  |  |  | if (buf->asize > buf->size) | 
| 865 | 792 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 866 | 792 |  |  |  |  |  | } | 
| 867 |  |  |  |  |  |  |  | 
| 868 | 0 |  |  |  |  |  | int git_buf_cmp(const git_buf *a, const git_buf *b) | 
| 869 |  |  |  |  |  |  | { | 
| 870 | 0 |  |  |  |  |  | int result = memcmp(a->ptr, b->ptr, min(a->size, b->size)); | 
| 871 | 0 | 0 |  |  |  |  | return (result != 0) ? result : | 
| 872 | 0 | 0 |  |  |  |  | (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; | 
| 873 |  |  |  |  |  |  | } | 
| 874 |  |  |  |  |  |  |  | 
| 875 | 0 |  |  |  |  |  | int git_buf_splice( | 
| 876 |  |  |  |  |  |  | git_buf *buf, | 
| 877 |  |  |  |  |  |  | size_t where, | 
| 878 |  |  |  |  |  |  | size_t nb_to_remove, | 
| 879 |  |  |  |  |  |  | const char *data, | 
| 880 |  |  |  |  |  |  | size_t nb_to_insert) | 
| 881 |  |  |  |  |  |  | { | 
| 882 |  |  |  |  |  |  | char *splice_loc; | 
| 883 |  |  |  |  |  |  | size_t new_size, alloc_size; | 
| 884 |  |  |  |  |  |  |  | 
| 885 | 0 | 0 |  |  |  |  | assert(buf && where <= buf->size && nb_to_remove <= buf->size - where); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 886 |  |  |  |  |  |  |  | 
| 887 | 0 |  |  |  |  |  | splice_loc = buf->ptr + where; | 
| 888 |  |  |  |  |  |  |  | 
| 889 |  |  |  |  |  |  | /* Ported from git.git | 
| 890 |  |  |  |  |  |  | * https://github.com/git/git/blob/16eed7c/strbuf.c#L159-176 | 
| 891 |  |  |  |  |  |  | */ | 
| 892 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&new_size, (buf->size - nb_to_remove), nb_to_insert); | 
|  |  | 0 |  |  |  |  |  | 
| 893 | 0 | 0 |  |  |  |  | GIT_ERROR_CHECK_ALLOC_ADD(&alloc_size, new_size, 1); | 
|  |  | 0 |  |  |  |  |  | 
| 894 | 0 | 0 |  |  |  |  | ENSURE_SIZE(buf, alloc_size); | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 895 |  |  |  |  |  |  |  | 
| 896 | 0 |  |  |  |  |  | memmove(splice_loc + nb_to_insert, | 
| 897 |  |  |  |  |  |  | splice_loc + nb_to_remove, | 
| 898 | 0 |  |  |  |  |  | buf->size - where - nb_to_remove); | 
| 899 |  |  |  |  |  |  |  | 
| 900 | 0 |  |  |  |  |  | memcpy(splice_loc, data, nb_to_insert); | 
| 901 |  |  |  |  |  |  |  | 
| 902 | 0 |  |  |  |  |  | buf->size = new_size; | 
| 903 | 0 |  |  |  |  |  | buf->ptr[buf->size] = '\0'; | 
| 904 | 0 |  |  |  |  |  | return 0; | 
| 905 |  |  |  |  |  |  | } | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | /* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */ | 
| 908 | 50 |  |  |  |  |  | int git_buf_quote(git_buf *buf) | 
| 909 |  |  |  |  |  |  | { | 
| 910 | 50 |  |  |  |  |  | const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' }; | 
| 911 | 50 |  |  |  |  |  | git_buf quoted = GIT_BUF_INIT; | 
| 912 | 50 |  |  |  |  |  | size_t i = 0; | 
| 913 | 50 |  |  |  |  |  | bool quote = false; | 
| 914 | 50 |  |  |  |  |  | int error = 0; | 
| 915 |  |  |  |  |  |  |  | 
| 916 |  |  |  |  |  |  | /* walk to the first char that needs quoting */ | 
| 917 | 50 | 50 |  |  |  |  | if (buf->size && buf->ptr[0] == '!') | 
|  |  | 50 |  |  |  |  |  | 
| 918 | 0 |  |  |  |  |  | quote = true; | 
| 919 |  |  |  |  |  |  |  | 
| 920 | 526 | 50 |  |  |  |  | for (i = 0; !quote && i < buf->size; i++) { | 
|  |  | 100 |  |  |  |  |  | 
| 921 | 476 | 50 |  |  |  |  | if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' || | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 922 | 476 | 50 |  |  |  |  | buf->ptr[i] < ' ' || buf->ptr[i] > '~') { | 
| 923 | 0 |  |  |  |  |  | quote = true; | 
| 924 | 0 |  |  |  |  |  | break; | 
| 925 |  |  |  |  |  |  | } | 
| 926 |  |  |  |  |  |  | } | 
| 927 |  |  |  |  |  |  |  | 
| 928 | 50 | 50 |  |  |  |  | if (!quote) | 
| 929 | 50 |  |  |  |  |  | goto done; | 
| 930 |  |  |  |  |  |  |  | 
| 931 | 0 |  |  |  |  |  | git_buf_putc("ed, '"'); | 
| 932 | 0 |  |  |  |  |  | git_buf_put("ed, buf->ptr, i); | 
| 933 |  |  |  |  |  |  |  | 
| 934 | 0 | 0 |  |  |  |  | for (; i < buf->size; i++) { | 
| 935 |  |  |  |  |  |  | /* whitespace - use the map above, which is ordered by ascii value */ | 
| 936 | 0 | 0 |  |  |  |  | if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') { | 
|  |  | 0 |  |  |  |  |  | 
| 937 | 0 |  |  |  |  |  | git_buf_putc("ed, '\\'); | 
| 938 | 0 |  |  |  |  |  | git_buf_putc("ed, whitespace[buf->ptr[i] - '\a']); | 
| 939 |  |  |  |  |  |  | } | 
| 940 |  |  |  |  |  |  |  | 
| 941 |  |  |  |  |  |  | /* double quote and backslash must be escaped */ | 
| 942 | 0 | 0 |  |  |  |  | else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') { | 
|  |  | 0 |  |  |  |  |  | 
| 943 | 0 |  |  |  |  |  | git_buf_putc("ed, '\\'); | 
| 944 | 0 |  |  |  |  |  | git_buf_putc("ed, buf->ptr[i]); | 
| 945 |  |  |  |  |  |  | } | 
| 946 |  |  |  |  |  |  |  | 
| 947 |  |  |  |  |  |  | /* escape anything unprintable as octal */ | 
| 948 | 0 | 0 |  |  |  |  | else if (buf->ptr[i] != ' ' && | 
|  |  | 0 |  |  |  |  |  | 
| 949 | 0 | 0 |  |  |  |  | (buf->ptr[i] < '!' || buf->ptr[i] > '~')) { | 
| 950 | 0 |  |  |  |  |  | git_buf_printf("ed, "\\%03o", (unsigned char)buf->ptr[i]); | 
| 951 |  |  |  |  |  |  | } | 
| 952 |  |  |  |  |  |  |  | 
| 953 |  |  |  |  |  |  | /* yay, printable! */ | 
| 954 |  |  |  |  |  |  | else { | 
| 955 | 0 |  |  |  |  |  | git_buf_putc("ed, buf->ptr[i]); | 
| 956 |  |  |  |  |  |  | } | 
| 957 |  |  |  |  |  |  | } | 
| 958 |  |  |  |  |  |  |  | 
| 959 | 0 |  |  |  |  |  | git_buf_putc("ed, '"'); | 
| 960 |  |  |  |  |  |  |  | 
| 961 | 0 | 0 |  |  |  |  | if (git_buf_oom("ed)) { | 
| 962 | 0 |  |  |  |  |  | error = -1; | 
| 963 | 0 |  |  |  |  |  | goto done; | 
| 964 |  |  |  |  |  |  | } | 
| 965 |  |  |  |  |  |  |  | 
| 966 | 0 |  |  |  |  |  | git_buf_swap("ed, buf); | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | done: | 
| 969 | 50 |  |  |  |  |  | git_buf_dispose("ed); | 
| 970 | 50 |  |  |  |  |  | return error; | 
| 971 |  |  |  |  |  |  | } | 
| 972 |  |  |  |  |  |  |  | 
| 973 |  |  |  |  |  |  | /* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */ | 
| 974 | 0 |  |  |  |  |  | int git_buf_unquote(git_buf *buf) | 
| 975 |  |  |  |  |  |  | { | 
| 976 |  |  |  |  |  |  | size_t i, j; | 
| 977 |  |  |  |  |  |  | char ch; | 
| 978 |  |  |  |  |  |  |  | 
| 979 | 0 |  |  |  |  |  | git_buf_rtrim(buf); | 
| 980 |  |  |  |  |  |  |  | 
| 981 | 0 | 0 |  |  |  |  | if (buf->size < 2 || buf->ptr[0] != '"' || buf->ptr[buf->size-1] != '"') | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 982 |  |  |  |  |  |  | goto invalid; | 
| 983 |  |  |  |  |  |  |  | 
| 984 | 0 | 0 |  |  |  |  | for (i = 0, j = 1; j < buf->size-1; i++, j++) { | 
| 985 | 0 |  |  |  |  |  | ch = buf->ptr[j]; | 
| 986 |  |  |  |  |  |  |  | 
| 987 | 0 | 0 |  |  |  |  | if (ch == '\\') { | 
| 988 | 0 | 0 |  |  |  |  | if (j == buf->size-2) | 
| 989 | 0 |  |  |  |  |  | goto invalid; | 
| 990 |  |  |  |  |  |  |  | 
| 991 | 0 |  |  |  |  |  | ch = buf->ptr[++j]; | 
| 992 |  |  |  |  |  |  |  | 
| 993 | 0 |  |  |  |  |  | switch (ch) { | 
| 994 |  |  |  |  |  |  | /* \" or \\ simply copy the char in */ | 
| 995 |  |  |  |  |  |  | case '"': case '\\': | 
| 996 | 0 |  |  |  |  |  | break; | 
| 997 |  |  |  |  |  |  |  | 
| 998 |  |  |  |  |  |  | /* add the appropriate escaped char */ | 
| 999 | 0 |  |  |  |  |  | case 'a': ch = '\a'; break; | 
| 1000 | 0 |  |  |  |  |  | case 'b': ch = '\b'; break; | 
| 1001 | 0 |  |  |  |  |  | case 'f': ch = '\f'; break; | 
| 1002 | 0 |  |  |  |  |  | case 'n': ch = '\n'; break; | 
| 1003 | 0 |  |  |  |  |  | case 'r': ch = '\r'; break; | 
| 1004 | 0 |  |  |  |  |  | case 't': ch = '\t'; break; | 
| 1005 | 0 |  |  |  |  |  | case 'v': ch = '\v'; break; | 
| 1006 |  |  |  |  |  |  |  | 
| 1007 |  |  |  |  |  |  | /* \xyz digits convert to the char*/ | 
| 1008 |  |  |  |  |  |  | case '0': case '1': case '2': case '3': | 
| 1009 | 0 | 0 |  |  |  |  | if (j == buf->size-3) { | 
| 1010 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, | 
| 1011 |  |  |  |  |  |  | "truncated quoted character \\%c", ch); | 
| 1012 | 0 |  |  |  |  |  | return -1; | 
| 1013 |  |  |  |  |  |  | } | 
| 1014 |  |  |  |  |  |  |  | 
| 1015 | 0 | 0 |  |  |  |  | if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' || | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 1016 | 0 | 0 |  |  |  |  | buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') { | 
| 1017 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, | 
| 1018 |  |  |  |  |  |  | "truncated quoted character \\%c%c%c", | 
| 1019 | 0 |  |  |  |  |  | buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]); | 
| 1020 | 0 |  |  |  |  |  | return -1; | 
| 1021 |  |  |  |  |  |  | } | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 | 0 |  |  |  |  |  | ch = ((buf->ptr[j] - '0') << 6) | | 
| 1024 | 0 |  |  |  |  |  | ((buf->ptr[j+1] - '0') << 3) | | 
| 1025 | 0 |  |  |  |  |  | (buf->ptr[j+2] - '0'); | 
| 1026 | 0 |  |  |  |  |  | j += 2; | 
| 1027 | 0 |  |  |  |  |  | break; | 
| 1028 |  |  |  |  |  |  |  | 
| 1029 |  |  |  |  |  |  | default: | 
| 1030 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid quoted character \\%c", ch); | 
| 1031 | 0 |  |  |  |  |  | return -1; | 
| 1032 |  |  |  |  |  |  | } | 
| 1033 |  |  |  |  |  |  | } | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 | 0 |  |  |  |  |  | buf->ptr[i] = ch; | 
| 1036 |  |  |  |  |  |  | } | 
| 1037 |  |  |  |  |  |  |  | 
| 1038 | 0 |  |  |  |  |  | buf->ptr[i] = '\0'; | 
| 1039 | 0 |  |  |  |  |  | buf->size = i; | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 | 0 |  |  |  |  |  | return 0; | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | invalid: | 
| 1044 | 0 |  |  |  |  |  | git_error_set(GIT_ERROR_INVALID, "invalid quoted line"); | 
| 1045 | 0 |  |  |  |  |  | return -1; | 
| 1046 |  |  |  |  |  |  | } |