diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-02-12 12:19:37 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-02-13 09:27:33 -0500 |
commit | f1453c59b2afb9dab43281bfe9f1ba34cf6e0d02 (patch) | |
tree | cb189e211547042080f35227b7e4d3f9b0c8ac2a /src/buffer.c | |
parent | 650e45f69124bd8b53ecefddeb214a82538ab2c1 (diff) | |
download | libgit2-f1453c59b2afb9dab43281bfe9f1ba34cf6e0d02.tar.gz |
Make our overflow check look more like gcc/clang's
Make our overflow checking look more like gcc and clang's, so that
we can substitute it out with the compiler instrinsics on platforms
that support it. This means dropping the ability to pass `NULL` as
an out parameter.
As a result, the macros also get updated to reflect this as well.
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 143 |
1 files changed, 76 insertions, 67 deletions
diff --git a/src/buffer.c b/src/buffer.c index 0d0314439..3deb0329c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -103,13 +103,14 @@ int git_buf_grow(git_buf *buffer, size_t target_size) int git_buf_grow_by(git_buf *buffer, size_t additional_size) { - if (GIT_ALLOC_OVERFLOW_ADD(buffer->size, additional_size)) { + size_t newsize; + + if (GIT_ADD_SIZET_OVERFLOW(&newsize, buffer->size, additional_size)) { buffer->ptr = git_buf__oom; return -1; } - return git_buf_try_grow( - buffer, buffer->size + additional_size, true, true); + return git_buf_try_grow(buffer, newsize, true, true); } void git_buf_free(git_buf *buf) @@ -146,12 +147,14 @@ void git_buf_clear(git_buf *buf) int git_buf_set(git_buf *buf, const void *data, size_t len) { + size_t alloclen; + if (len == 0 || data == NULL) { git_buf_clear(buf); } else { if (data != buf->ptr) { - GITERR_CHECK_ALLOC_ADD(len, 1); - ENSURE_SIZE(buf, len + 1); + GITERR_CHECK_ALLOC_ADD(&alloclen, len, 1); + ENSURE_SIZE(buf, alloclen); memmove(buf->ptr, data, len); } @@ -180,8 +183,9 @@ int git_buf_sets(git_buf *buf, const char *string) int git_buf_putc(git_buf *buf, char c) { - GITERR_CHECK_ALLOC_ADD(buf->size, 2); - ENSURE_SIZE(buf, buf->size + 2); + size_t new_size; + GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, 2); + ENSURE_SIZE(buf, new_size); buf->ptr[buf->size++] = c; buf->ptr[buf->size] = '\0'; return 0; @@ -189,9 +193,10 @@ int git_buf_putc(git_buf *buf, char c) int git_buf_putcn(git_buf *buf, char c, size_t len) { - GITERR_CHECK_ALLOC_ADD(buf->size, len); - GITERR_CHECK_ALLOC_ADD(buf->size + len, 1); - ENSURE_SIZE(buf, buf->size + len + 1); + size_t new_size; + GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, len); + GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1); + ENSURE_SIZE(buf, new_size); memset(buf->ptr + buf->size, c, len); buf->size += len; buf->ptr[buf->size] = '\0'; @@ -201,10 +206,13 @@ int git_buf_putcn(git_buf *buf, char c, size_t len) int git_buf_put(git_buf *buf, const char *data, size_t len) { if (len) { + size_t new_size; + assert(data); - GITERR_CHECK_ALLOC_ADD(buf->size, len); - GITERR_CHECK_ALLOC_ADD(buf->size + len, 1); - ENSURE_SIZE(buf, buf->size + len + 1); + + GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, len); + GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1); + ENSURE_SIZE(buf, new_size); memmove(buf->ptr + buf->size, data, len); buf->size += len; buf->ptr[buf->size] = '\0'; @@ -226,12 +234,13 @@ int git_buf_encode_base64(git_buf *buf, const char *data, size_t len) size_t extra = len % 3; uint8_t *write, a, b, c; const uint8_t *read = (const uint8_t *)data; - size_t blocks = (len / 3) + !!extra; + size_t blocks = (len / 3) + !!extra, alloclen; + + GITERR_CHECK_ALLOC_ADD(&blocks, blocks, 1); + GITERR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 4); + GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size); - GITERR_CHECK_ALLOC_MULTIPLY(blocks, 4); - GITERR_CHECK_ALLOC_ADD(buf->size, 4 * blocks); - GITERR_CHECK_ALLOC_ADD(buf->size + 4 * blocks, 1); - ENSURE_SIZE(buf, buf->size + 4 * blocks + 1); + ENSURE_SIZE(buf, alloclen); write = (uint8_t *)&buf->ptr[buf->size]; /* convert each run of 3 bytes into 4 output bytes */ @@ -282,12 +291,12 @@ int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len) { size_t i; int8_t a, b, c, d; - size_t orig_size = buf->size; + size_t orig_size = buf->size, new_size; assert(len % 4 == 0); - GITERR_CHECK_ALLOC_ADD(buf->size, len / 4 * 3); - GITERR_CHECK_ALLOC_ADD(buf->size + (len / 4 * 3), 1); - ENSURE_SIZE(buf, buf->size + (len / 4 * 3) + 1); + GITERR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size); + GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1); + ENSURE_SIZE(buf, new_size); for (i = 0; i < len; i += 4) { if ((a = BASE64_DECODE_VALUE(base64[i])) < 0 || @@ -315,12 +324,13 @@ static const char b85str[] = int git_buf_encode_base85(git_buf *buf, const char *data, size_t len) { - size_t blocks = (len / 4) + !!(len % 4); + size_t blocks = (len / 4) + !!(len % 4), alloclen; - GITERR_CHECK_ALLOC_MULTIPLY(blocks, 5); - GITERR_CHECK_ALLOC_ADD(buf->size, 5 * blocks); - GITERR_CHECK_ALLOC_ADD(buf->size + 5 * blocks, 1); - ENSURE_SIZE(buf, buf->size + blocks * 5 + 1); + GITERR_CHECK_ALLOC_MULTIPLY(&alloclen, blocks, 5); + GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, buf->size); + GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1); + + ENSURE_SIZE(buf, alloclen); while (len) { uint32_t acc = 0; @@ -353,15 +363,11 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len) int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) { - size_t expected_size = strlen(format); + size_t expected_size, new_size; int len; - GITERR_CHECK_ALLOC_MULTIPLY(expected_size, 2); - expected_size *= 2; - - GITERR_CHECK_ALLOC_ADD(expected_size, buf->size); - expected_size += buf->size; - + GITERR_CHECK_ALLOC_MULTIPLY(&expected_size, strlen(format), 2); + GITERR_CHECK_ALLOC_ADD(&expected_size, expected_size, buf->size); ENSURE_SIZE(buf, expected_size); while (1) { @@ -387,9 +393,9 @@ int git_buf_vprintf(git_buf *buf, const char *format, va_list ap) break; } - GITERR_CHECK_ALLOC_ADD(buf->size, len); - GITERR_CHECK_ALLOC_ADD(buf->size + len, 1); - ENSURE_SIZE(buf, buf->size + len + 1); + GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, len); + GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1); + ENSURE_SIZE(buf, new_size); } return 0; @@ -516,9 +522,11 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...) continue; segment_len = strlen(segment); - total_size += segment_len; + + GITERR_CHECK_ALLOC_ADD(&total_size, total_size, segment_len); + if (segment_len == 0 || segment[segment_len - 1] != separator) - ++total_size; /* space for separator */ + GITERR_CHECK_ALLOC_ADD(&total_size, total_size, 1); } va_end(ap); @@ -526,8 +534,8 @@ int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...) if (total_size == 0) return 0; - GITERR_CHECK_ALLOC_ADD(total_size, 1); - if (git_buf_grow_by(buf, total_size + 1) < 0) + GITERR_CHECK_ALLOC_ADD(&total_size, total_size, 1); + if (git_buf_grow_by(buf, total_size) < 0) return -1; out = buf->ptr + buf->size; @@ -588,6 +596,7 @@ int git_buf_join( { size_t strlen_a = str_a ? strlen(str_a) : 0; size_t strlen_b = strlen(str_b); + size_t alloc_len; int need_sep = 0; ssize_t offset_a = -1; @@ -605,10 +614,10 @@ int git_buf_join( if (str_a >= buf->ptr && str_a < buf->ptr + buf->size) offset_a = str_a - buf->ptr; - GITERR_CHECK_ALLOC_ADD(strlen_a, strlen_b); - GITERR_CHECK_ALLOC_ADD(strlen_a + strlen_b, need_sep); - GITERR_CHECK_ALLOC_ADD(strlen_a + strlen_b + need_sep, 1); - if (git_buf_grow(buf, strlen_a + strlen_b + need_sep + 1) < 0) + GITERR_CHECK_ALLOC_ADD(&alloc_len, strlen_a, strlen_b); + GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, need_sep); + GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1); + if (git_buf_grow(buf, alloc_len) < 0) return -1; assert(buf->ptr); @@ -636,7 +645,10 @@ int git_buf_join3( const char *str_b, const char *str_c) { - size_t len_a = strlen(str_a), len_b = strlen(str_b), len_c = strlen(str_c); + size_t len_a = strlen(str_a), + len_b = strlen(str_b), + len_c = strlen(str_c), + len_total; int sep_a = 0, sep_b = 0; char *tgt; @@ -656,12 +668,12 @@ int git_buf_join3( sep_b = (str_b[len_b - 1] != separator); } - GITERR_CHECK_ALLOC_ADD(len_a, sep_a); - GITERR_CHECK_ALLOC_ADD(len_a + sep_a, len_b); - GITERR_CHECK_ALLOC_ADD(len_a + sep_a + len_b, sep_b); - GITERR_CHECK_ALLOC_ADD(len_a + sep_a + len_b + sep_b, len_c); - GITERR_CHECK_ALLOC_ADD(len_a + sep_a + len_b + sep_b + len_c, 1); - if (git_buf_grow(buf, len_a + sep_a + len_b + sep_b + len_c + 1) < 0) + GITERR_CHECK_ALLOC_ADD(&len_total, len_a, sep_a); + GITERR_CHECK_ALLOC_ADD(&len_total, len_total, len_b); + GITERR_CHECK_ALLOC_ADD(&len_total, len_total, sep_b); + GITERR_CHECK_ALLOC_ADD(&len_total, len_total, len_c); + GITERR_CHECK_ALLOC_ADD(&len_total, len_total, 1); + if (git_buf_grow(buf, len_total) < 0) return -1; tgt = buf->ptr; @@ -714,28 +726,25 @@ int git_buf_splice( const char *data, size_t nb_to_insert) { - size_t new_size; + char *splice_loc; + size_t new_size, alloc_size; - assert(buf && - where <= git_buf_len(buf) && - where + nb_to_remove <= git_buf_len(buf)); + assert(buf && where <= buf->size && nb_to_remove <= buf->size - where); + + splice_loc = buf->ptr + where; /* Ported from git.git * https://github.com/git/git/blob/16eed7c/strbuf.c#L159-176 */ - new_size = buf->size - nb_to_remove; - - GITERR_CHECK_ALLOC_ADD(new_size, nb_to_insert); - new_size += nb_to_insert; - - GITERR_CHECK_ALLOC_ADD(new_size, 1); - ENSURE_SIZE(buf, new_size + 1); + GITERR_CHECK_ALLOC_ADD(&new_size, (buf->size - nb_to_remove), nb_to_insert); + GITERR_CHECK_ALLOC_ADD(&alloc_size, new_size, 1); + ENSURE_SIZE(buf, alloc_size); - memmove(buf->ptr + where + nb_to_insert, - buf->ptr + where + nb_to_remove, - buf->size - where - nb_to_remove); + memmove(splice_loc + nb_to_insert, + splice_loc + nb_to_remove, + buf->size - where - nb_to_remove); - memcpy(buf->ptr + where, data, nb_to_insert); + memcpy(splice_loc, data, nb_to_insert); buf->size = new_size; buf->ptr[buf->size] = '\0'; |