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