Commit f1453c59 by Edward Thomson

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.
parent 650e45f6
......@@ -51,10 +51,9 @@ GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
if (a->size < 8) {
new_size = 8;
} else {
if (GIT_ALLOC_OVERFLOW_MULTIPLY(a->size, 3 / 2))
if (GIT_MULTIPLY_SIZET_OVERFLOW(&new_size, a->size, 3))
goto on_oom;
new_size = a->size * 3 / 2;
new_size /= 2;
}
if ((new_array = git__reallocarray(a->ptr, new_size, item_size)) == NULL)
......
......@@ -36,14 +36,14 @@ static void origin_decref(git_blame__origin *o)
static int make_origin(git_blame__origin **out, git_commit *commit, const char *path)
{
git_blame__origin *o;
size_t path_len = strlen(path);
size_t path_len = strlen(path), alloc_len;
int error = 0;
GITERR_CHECK_ALLOC_ADD(sizeof(*o), path_len);
GITERR_CHECK_ALLOC_ADD(sizeof(*o) + path_len, 1);
o = git__calloc(1, sizeof(*o) + path_len + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*o), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
o = git__calloc(1, alloc_len);
GITERR_CHECK_ALLOC(o);
o->commit = commit;
o->refcnt = 1;
strcpy(o->path, path);
......
......@@ -13,7 +13,7 @@ int git_buf_text_puts_escaped(
const char *esc_with)
{
const char *scan;
size_t total = 0, esc_len = strlen(esc_with), count;
size_t total = 0, esc_len = strlen(esc_with), count, alloclen;
if (!string)
return 0;
......@@ -29,8 +29,8 @@ int git_buf_text_puts_escaped(
scan += count;
}
GITERR_CHECK_ALLOC_ADD(total, 1);
if (git_buf_grow_by(buf, total + 1) < 0)
GITERR_CHECK_ALLOC_ADD(&alloclen, total, 1);
if (git_buf_grow_by(buf, alloclen) < 0)
return -1;
for (scan = string; *scan; ) {
......@@ -66,6 +66,7 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src)
const char *scan = src->ptr;
const char *scan_end = src->ptr + src->size;
const char *next = memchr(scan, '\r', src->size);
size_t new_size;
char *out;
assert(tgt != src);
......@@ -74,8 +75,8 @@ int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src)
return git_buf_set(tgt, src->ptr, src->size);
/* reduce reallocs while in the loop */
GITERR_CHECK_ALLOC_ADD(src->size, 1);
if (git_buf_grow(tgt, src->size + 1) < 0)
GITERR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
if (git_buf_grow(tgt, new_size) < 0)
return -1;
out = tgt->ptr;
......@@ -113,6 +114,7 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
const char *end = start + src->size;
const char *scan = start;
const char *next = memchr(scan, '\n', src->size);
size_t alloclen;
assert(tgt != src);
......@@ -120,9 +122,9 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
return git_buf_set(tgt, src->ptr, src->size);
/* attempt to reduce reallocs while in the loop */
GITERR_CHECK_ALLOC_ADD(src->size, src->size >> 4);
GITERR_CHECK_ALLOC_ADD(src->size + (src->size >> 4), 1);
if (git_buf_grow(tgt, src->size + (src->size >> 4) + 1) < 0)
GITERR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
if (git_buf_grow(tgt, alloclen) < 0)
return -1;
tgt->size = 0;
......@@ -135,8 +137,8 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
return GIT_PASSTHROUGH;
}
GITERR_CHECK_ALLOC_ADD(copylen, 3);
if (git_buf_grow_by(tgt, copylen + 3) < 0)
GITERR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
if (git_buf_grow_by(tgt, alloclen) < 0)
return -1;
if (next > scan) {
......
......@@ -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';
......
......@@ -176,21 +176,21 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
memcpy((PTR), &_tmpl, sizeof(_tmpl)); } while (0)
/** Check for integer overflow from addition or multiplication */
#define GIT_ALLOC_OVERFLOW_ADD(one, two) \
(!git__add_sizet_overflow(NULL, (one), (two)) ? (giterr_set_oom(), 1) : 0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_ADD_SIZET_OVERFLOW(out, one, two) \
(git__add_sizet_overflow(out, one, two) ? (giterr_set_oom(), 1) : 0)
/** Check for integer overflow from multiplication */
#define GIT_ALLOC_OVERFLOW_MULTIPLY(one, two) \
(!git__multiply_sizet_overflow(NULL, (one), (two)) ? (giterr_set_oom(), 1) : 0)
/** Check for additive overflow, setting an error if would occur. */
#define GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize) \
(git__multiply_sizet_overflow(out, nelem, elsize) ? (giterr_set_oom(), 1) : 0)
/** Check for additive overflow, failing if it would occur. */
#define GITERR_CHECK_ALLOC_ADD(one, two) \
if (GIT_ALLOC_OVERFLOW_ADD(one, two)) { return -1; }
#define GITERR_CHECK_ALLOC_ADD(out, one, two) \
if (GIT_ADD_SIZET_OVERFLOW(out, one, two)) { return -1; }
/** Check for multiplicative overflow, failing if it would occur. */
#define GITERR_CHECK_ALLOC_MULTIPLY(nelem, elsize) \
if (GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize)) { return -1; }
#define GITERR_CHECK_ALLOC_MULTIPLY(out, nelem, elsize) \
if (GIT_MULTIPLY_SIZET_OVERFLOW(out, nelem, elsize)) { return -1; }
/* NOTE: other giterr functions are in the public errors.h header file */
......
......@@ -885,7 +885,7 @@ static char *reader_readline(struct reader *reader, bool skip_whitespace)
{
char *line = NULL;
char *line_src, *line_end;
size_t line_len;
size_t line_len, alloc_len;
line_src = reader->read_ptr;
......@@ -903,8 +903,8 @@ static char *reader_readline(struct reader *reader, bool skip_whitespace)
line_len = line_end - line_src;
if (GIT_ALLOC_OVERFLOW_ADD(line_len, 1) ||
(line = git__malloc(line_len + 1)) == NULL) {
if (GIT_ADD_SIZET_OVERFLOW(&alloc_len, line_len, 1) ||
(line = git__malloc(alloc_len)) == NULL) {
return NULL;
}
......@@ -959,7 +959,7 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
int c, rpos;
char *first_quote, *last_quote;
git_buf buf = GIT_BUF_INIT;
size_t quoted_len, base_name_len = strlen(base_name);
size_t quoted_len, alloc_len, base_name_len = strlen(base_name);
/*
* base_name is what came before the space. We should be at the
......@@ -976,10 +976,10 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
return -1;
}
GITERR_CHECK_ALLOC_ADD(base_name_len, quoted_len);
GITERR_CHECK_ALLOC_ADD(base_name_len + quoted_len, 2);
GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
git_buf_grow(&buf, base_name_len + quoted_len + 2);
git_buf_grow(&buf, alloc_len);
git_buf_printf(&buf, "%s.", base_name);
rpos = 0;
......@@ -1050,9 +1050,7 @@ static int parse_section_header(struct reader *reader, char **section_out)
return -1;
}
line_len = (size_t)(name_end - line);
GITERR_CHECK_ALLOC_ADD(line_len, 1);
GITERR_CHECK_ALLOC_ADD(&line_len, (size_t)(name_end - line), 1);
name = git__malloc(line_len);
GITERR_CHECK_ALLOC(name);
......@@ -1615,10 +1613,10 @@ static char *escape_value(const char *ptr)
static char *fixup_line(const char *ptr, int quote_count)
{
char *str, *out, *esc;
size_t ptr_len = strlen(ptr);
size_t ptr_len = strlen(ptr), alloc_len;
if (GIT_ALLOC_OVERFLOW_ADD(ptr_len, 1) ||
(str = git__malloc(ptr_len + 1)) == NULL) {
if (GIT_ADD_SIZET_OVERFLOW(&alloc_len, ptr_len, 1) ||
(str = git__malloc(alloc_len)) == NULL) {
return NULL;
}
......
......@@ -57,7 +57,7 @@ int git__delta_apply(
size_t delta_len)
{
const unsigned char *delta_end = delta + delta_len;
size_t base_sz, res_sz;
size_t base_sz, res_sz, alloc_sz;
unsigned char *res_dp;
/* Check that the base size matches the data we were given;
......@@ -74,8 +74,8 @@ int git__delta_apply(
return -1;
}
GITERR_CHECK_ALLOC_ADD(res_sz, 1);
res_dp = git__malloc(res_sz + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_sz, res_sz, 1);
res_dp = git__malloc(alloc_sz);
GITERR_CHECK_ALLOC(res_dp);
res_dp[res_sz] = '\0';
......
......@@ -122,20 +122,13 @@ struct git_delta_index {
static int lookup_index_alloc(
void **out, unsigned long *out_len, size_t entries, size_t hash_count)
{
size_t entries_len, hash_len,
index_len = sizeof(struct git_delta_index);
size_t entries_len, hash_len, index_len;
GITERR_CHECK_ALLOC_MULTIPLY(entries, sizeof(struct index_entry));
entries_len = entries * sizeof(struct index_entry);
GITERR_CHECK_ALLOC_MULTIPLY(&entries_len, entries, sizeof(struct index_entry));
GITERR_CHECK_ALLOC_MULTIPLY(&hash_len, hash_count, sizeof(struct index_entry *));
GITERR_CHECK_ALLOC_ADD(index_len, entries_len);
index_len += entries_len;
GITERR_CHECK_ALLOC_MULTIPLY(hash_count, sizeof(struct index_entry *));
hash_len = hash_count * sizeof(struct index_entry *);
GITERR_CHECK_ALLOC_ADD(index_len, hash_len);
index_len += hash_len;
GITERR_CHECK_ALLOC_ADD(&index_len, sizeof(struct git_delta_index), entries_len);
GITERR_CHECK_ALLOC_ADD(&index_len, index_len, hash_len);
if (!git__is_ulong(index_len)) {
giterr_set(GITERR_NOMEMORY, "Overly large delta");
......
......@@ -1527,6 +1527,7 @@ int git_diff_format_email(
char *summary = NULL, *loc = NULL;
bool ignore_marker;
unsigned int format_flags = 0;
size_t allocsize;
int error;
assert(out && diff && opts);
......@@ -1558,8 +1559,8 @@ int git_diff_format_email(
goto on_error;
}
GITERR_CHECK_ALLOC_ADD(offset, 1);
summary = git__calloc(offset + 1, sizeof(char));
GITERR_CHECK_ALLOC_ADD(&allocsize, offset, 1);
summary = git__calloc(allocsize, sizeof(char));
GITERR_CHECK_ALLOC(summary);
strncpy(summary, opts->summary, offset);
......
......@@ -163,12 +163,13 @@ static int diff_driver_alloc(
{
git_diff_driver *driver;
size_t driverlen = sizeof(git_diff_driver),
namelen = strlen(name);
namelen = strlen(name),
alloclen;
GITERR_CHECK_ALLOC_ADD(driverlen, namelen);
GITERR_CHECK_ALLOC_ADD(driverlen + namelen, 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, driverlen, namelen);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
driver = git__calloc(1, driverlen + namelen + 1);
driver = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(driver);
memcpy(driver->name, name, namelen);
......
......@@ -388,16 +388,11 @@ static int diff_patch_with_delta_alloc(
diff_patch_with_delta *pd;
size_t old_len = *old_path ? strlen(*old_path) : 0;
size_t new_len = *new_path ? strlen(*new_path) : 0;
size_t alloc_len = sizeof(*pd);
size_t alloc_len;
GITERR_CHECK_ALLOC_ADD(alloc_len, old_len);
alloc_len += old_len;
GITERR_CHECK_ALLOC_ADD(alloc_len, new_len);
alloc_len += new_len;
GITERR_CHECK_ALLOC_ADD(alloc_len, 2);
alloc_len += 2;
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*pd), old_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, new_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
*out = pd = git__calloc(1, alloc_len);
GITERR_CHECK_ALLOC(pd);
......
......@@ -811,6 +811,7 @@ int git_diff_find_similar(
size_t num_deltas, num_srcs = 0, num_tgts = 0;
size_t tried_srcs = 0, tried_tgts = 0;
size_t num_rewrites = 0, num_updates = 0, num_bumped = 0;
size_t sigcache_size;
void **sigcache = NULL; /* cache of similarity metric file signatures */
diff_find_match *tgt2src = NULL;
diff_find_match *src2tgt = NULL;
......@@ -831,8 +832,8 @@ int git_diff_find_similar(
if ((opts.flags & GIT_DIFF_FIND_ALL) == 0)
goto cleanup;
GITERR_CHECK_ALLOC_MULTIPLY(num_deltas, 2);
sigcache = git__calloc(num_deltas * 2, sizeof(void *));
GITERR_CHECK_ALLOC_MULTIPLY(&sigcache_size, num_deltas, 2);
sigcache = git__calloc(sigcache_size, sizeof(void *));
GITERR_CHECK_ALLOC(sigcache);
/* Label rename sources and targets
......
......@@ -194,7 +194,7 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode)
{
int compression, error = -1;
size_t path_len;
size_t path_len, alloc_len;
/* opening an already open buffer is a programming error;
* assert that this never happens instead of returning
......@@ -271,8 +271,8 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags, mode_t mode
GITERR_CHECK_ALLOC(file->path_original);
/* create the locking path by appending ".lock" to the original */
GITERR_CHECK_ALLOC_ADD(path_len, GIT_FILELOCK_EXTLENGTH);
file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
GITERR_CHECK_ALLOC_ADD(&alloc_len, path_len, GIT_FILELOCK_EXTLENGTH);
file->path_lock = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(file->path_lock);
memcpy(file->path_lock, file->path_original, path_len);
......@@ -408,7 +408,7 @@ int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
int git_filebuf_printf(git_filebuf *file, const char *format, ...)
{
va_list arglist;
size_t space_left, len;
size_t space_left, len, alloclen;
int written, res;
char *tmp_buffer;
......@@ -439,8 +439,8 @@ int git_filebuf_printf(git_filebuf *file, const char *format, ...)
} while (len + 1 <= space_left);
if (GIT_ALLOC_OVERFLOW_ADD(len, 1) ||
!(tmp_buffer = git__malloc(len + 1))) {
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, len, 1) ||
!(tmp_buffer = git__malloc(alloclen))) {
file->last_error = BUFERR_MEM;
return -1;
}
......
......@@ -124,6 +124,7 @@ mode_t git_futils_canonical_mode(mode_t raw_mode)
int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
{
ssize_t read_size = 0;
size_t alloc_len;
git_buf_clear(buf);
......@@ -132,8 +133,8 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
return -1;
}
GITERR_CHECK_ALLOC_ADD(len, 1);
if (git_buf_grow(buf, len + 1) < 0)
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
if (git_buf_grow(buf, alloc_len) < 0)
return -1;
/* p_read loops internally to read len bytes */
......@@ -455,7 +456,13 @@ int git_futils_mkdir_ext(
}
if (opts->dir_map && opts->pool) {
char *cache_path = git_pool_malloc(opts->pool, make_path.size + 1);
char *cache_path;
size_t alloc_size;
GITERR_CHECK_ALLOC_ADD(&alloc_size, make_path.size, 1);
if (!git__is_uint32(alloc_size))
return -1;
cache_path = git_pool_malloc(opts->pool, (uint32_t)alloc_size);
GITERR_CHECK_ALLOC(cache_path);
memcpy(cache_path, make_path.ptr, make_path.size + 1);
......@@ -715,9 +722,10 @@ static int cp_link(const char *from, const char *to, size_t link_size)
int error = 0;
ssize_t read_len;
char *link_data;
size_t alloc_size;
GITERR_CHECK_ALLOC_ADD(link_size, 1);
link_data = git__malloc(link_size + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_size, link_size, 1);
link_data = git__malloc(alloc_size);
GITERR_CHECK_ALLOC(link_data);
read_len = p_readlink(from, link_data, link_size);
......
......@@ -245,14 +245,9 @@ int git_filter_register(
if (filter_def_scan_attrs(&attrs, &nattr, &nmatch, filter->attributes) < 0)
return -1;
GITERR_CHECK_ALLOC_MULTIPLY(nattr, 2);
alloc_len = nattr * 2;
GITERR_CHECK_ALLOC_MULTIPLY(alloc_len, sizeof(char *));
alloc_len *= sizeof(char *);
GITERR_CHECK_ALLOC_ADD(alloc_len, sizeof(git_filter_def));
alloc_len += sizeof(git_filter_def);
GITERR_CHECK_ALLOC_MULTIPLY(&alloc_len, nattr, 2);
GITERR_CHECK_ALLOC_MULTIPLY(&alloc_len, alloc_len, sizeof(char *));
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, sizeof(git_filter_def));
fdef = git__calloc(1, alloc_len);
GITERR_CHECK_ALLOC(fdef);
......@@ -385,12 +380,12 @@ static int filter_list_new(
git_filter_list **out, const git_filter_source *src)
{
git_filter_list *fl = NULL;
size_t pathlen = src->path ? strlen(src->path) : 0;
size_t pathlen = src->path ? strlen(src->path) : 0, alloclen;
GITERR_CHECK_ALLOC_ADD(sizeof(git_filter_list), pathlen);
GITERR_CHECK_ALLOC_ADD(sizeof(git_filter_list) + pathlen, 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_filter_list), pathlen);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
fl = git__calloc(1, sizeof(git_filter_list) + pathlen + 1);
fl = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(fl);
if (src->path)
......
......@@ -770,7 +770,7 @@ static int index_entry_create(
git_repository *repo,
const char *path)
{
size_t pathlen = strlen(path);
size_t pathlen = strlen(path), alloclen;
struct entry_internal *entry;
if (!git_path_isvalid(repo, path,
......@@ -779,9 +779,9 @@ static int index_entry_create(
return -1;
}
GITERR_CHECK_ALLOC_ADD(sizeof(struct entry_internal), pathlen);
GITERR_CHECK_ALLOC_ADD(sizeof(struct entry_internal) + pathlen, 1);
entry = git__calloc(1, sizeof(struct entry_internal) + pathlen + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(struct entry_internal), pathlen);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
entry = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(entry);
entry->pathlen = pathlen;
......@@ -829,14 +829,15 @@ static int index_entry_init(
static git_index_reuc_entry *reuc_entry_alloc(const char *path)
{
size_t pathlen = strlen(path),
structlen = sizeof(struct reuc_entry_internal);
structlen = sizeof(struct reuc_entry_internal),
alloclen;
struct reuc_entry_internal *entry;
if (GIT_ALLOC_OVERFLOW_ADD(structlen, pathlen) ||
GIT_ALLOC_OVERFLOW_ADD(structlen + pathlen, 1))
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, structlen, pathlen) ||
GIT_ADD_SIZET_OVERFLOW(&alloclen, alloclen, 1))
return NULL;
entry = git__calloc(1, structlen + pathlen + 1);
entry = git__calloc(1, alloclen);
if (!entry)
return NULL;
......
......@@ -35,6 +35,13 @@ GIT_INLINE(int) git__is_ulong(git_off_t p)
return p == (git_off_t)r;
}
/** @return true if p fits into the range of an int */
GIT_INLINE(int) git__is_int(long long p)
{
int r = (int)p;
return p == (long long)r;
}
/**
* Sets `one + two` into `out`, unless the arithmetic would overflow.
* @return true if the result fits in a `uint64_t`, false on overflow.
......@@ -42,10 +49,9 @@ GIT_INLINE(int) git__is_ulong(git_off_t p)
GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t two)
{
if (UINT64_MAX - one < two)
return false;
if (out)
*out = one + two;
return true;
return true;
*out = one + two;
return false;
}
/**
......@@ -55,10 +61,9 @@ GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t
GIT_INLINE(bool) git__add_sizet_overflow(size_t *out, size_t one, size_t two)
{
if (SIZE_MAX - one < two)
return false;
if (out)
*out = one + two;
return true;
return true;
*out = one + two;
return false;
}
/**
......@@ -68,10 +73,9 @@ GIT_INLINE(bool) git__add_sizet_overflow(size_t *out, size_t one, size_t two)
GIT_INLINE(bool) git__multiply_sizet_overflow(size_t *out, size_t one, size_t two)
{
if (one && SIZE_MAX / one < two)
return false;
if (out)
*out = one * two;
return true;
return true;
*out = one * two;
return false;
}
#endif /* INCLUDE_integer_h__ */
......@@ -344,11 +344,8 @@ static int tree_iterator__push_frame(tree_iterator *ti)
for (i = head->current; i < head->next; ++i)
n_entries += git_tree_entrycount(head->entries[i]->tree);
GITERR_CHECK_ALLOC_MULTIPLY(sizeof(tree_iterator_entry *), n_entries);
alloclen = sizeof(tree_iterator_entry *) * n_entries;
GITERR_CHECK_ALLOC_ADD(alloclen, sizeof(tree_iterator_frame));
alloclen += sizeof(tree_iterator_frame);
GITERR_CHECK_ALLOC_MULTIPLY(&alloclen, sizeof(tree_iterator_entry *), n_entries);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, sizeof(tree_iterator_frame));
tf = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(tf);
......
......@@ -1169,8 +1169,7 @@ int git_merge_diff_list__find_renames(
goto done;
if (diff_list->conflicts.length <= opts->target_limit) {
GITERR_CHECK_ALLOC_MULTIPLY(diff_list->conflicts.length, 3);
cache_size = diff_list->conflicts.length * 3;
GITERR_CHECK_ALLOC_MULTIPLY(&cache_size, diff_list->conflicts.length, 3);
cache = git__calloc(cache_size, sizeof(void *));
GITERR_CHECK_ALLOC(cache);
......@@ -2224,13 +2223,13 @@ static int merge_ancestor_head(
size_t their_heads_len)
{
git_oid *oids, ancestor_oid;
size_t i;
size_t i, alloc_len;
int error = 0;
assert(repo && our_head && their_heads);
GITERR_CHECK_ALLOC_ADD(their_heads_len, 1);
oids = git__calloc(their_heads_len + 1, sizeof(git_oid));
GITERR_CHECK_ALLOC_ADD(&alloc_len, their_heads_len, 1);
oids = git__calloc(alloc_len, sizeof(git_oid));
GITERR_CHECK_ALLOC(oids);
git_oid_cpy(&oids[0], git_commit_id(our_head->commit));
......
......@@ -216,30 +216,31 @@ int git_odb__hashfd_filtered(
int git_odb__hashlink(git_oid *out, const char *path)
{
struct stat st;
size_t size;
int size;
int result;
if (git_path_lstat(path, &st) < 0)
return -1;
if (!git__is_sizet(st.st_size)) {
if (!git__is_int(st.st_size) || (int)st.st_size < 0) {
giterr_set(GITERR_FILESYSTEM, "File size overflow for 32-bit systems");
return -1;
}
size = (size_t)st.st_size;
size = (int)st.st_size;
if (S_ISLNK(st.st_mode)) {
char *link_data;
ssize_t read_len;
int read_len;
size_t alloc_size;
GITERR_CHECK_ALLOC_ADD(size, 1);
link_data = git__malloc(size + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_size, size, 1);
link_data = git__malloc(alloc_size);
GITERR_CHECK_ALLOC(link_data);
read_len = p_readlink(path, link_data, size);
link_data[size] = '\0';
if (read_len != (ssize_t)size) {
if (read_len != size) {
giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path);
git__free(link_data);
return -1;
......
......@@ -63,10 +63,12 @@ typedef struct {
static int object_file_name(
git_buf *name, const loose_backend *be, const git_oid *id)
{
size_t alloclen;
/* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
GITERR_CHECK_ALLOC_ADD(be->objects_dirlen, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(be->objects_dirlen + GIT_OID_HEXSZ, 3);
if (git_buf_grow(name, be->objects_dirlen + GIT_OID_HEXSZ + 3) < 0)
GITERR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
if (git_buf_grow(name, alloclen) < 0)
return -1;
git_buf_set(name, be->objects_dir, be->objects_dirlen);
......@@ -263,15 +265,15 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
{
unsigned char *buf, *head = hb;
size_t tail;
size_t tail, alloc_size;
/*
* allocate a buffer to hold the inflated data and copy the
* initial sequence of inflated data from the tail of the
* head buffer, if any.
*/
if (GIT_ALLOC_OVERFLOW_ADD(hdr->size, 1) ||
(buf = git__malloc(hdr->size + 1)) == NULL) {
if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr->size, 1) ||
(buf = git__malloc(alloc_size)) == NULL) {
inflateEnd(s);
return NULL;
}
......@@ -309,7 +311,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
{
unsigned char *in, *buf;
obj_hdr hdr;
size_t len, used;
size_t len, used, alloclen;
/*
* read the object header, which is an (uncompressed)
......@@ -324,8 +326,8 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
/*
* allocate a buffer and inflate the data into it
*/
GITERR_CHECK_ALLOC_ADD(hdr.size, 1);
buf = git__malloc(hdr.size + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, hdr.size, 1);
buf = git__malloc(alloclen);
GITERR_CHECK_ALLOC(buf);
in = ((unsigned char *)obj->ptr) + used;
......@@ -519,14 +521,14 @@ static int locate_object_short_oid(
size_t len)
{
char *objects_dir = backend->objects_dir;
size_t dir_len = strlen(objects_dir);
size_t dir_len = strlen(objects_dir), alloc_len;
loose_locate_object_state state;
int error;
/* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
GITERR_CHECK_ALLOC_ADD(dir_len, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(dir_len + GIT_OID_HEXSZ, 3);
if (git_buf_grow(object_location, dir_len + 3 + GIT_OID_HEXSZ) < 0)
GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
if (git_buf_grow(object_location, alloc_len) < 0)
return -1;
git_buf_set(object_location, objects_dir, dir_len);
......@@ -569,11 +571,11 @@ static int locate_object_short_oid(
return error;
/* Update the location according to the oid obtained */
GITERR_CHECK_ALLOC_ADD(dir_len, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(dir_len + GIT_OID_HEXSZ, 2);
GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
git_buf_truncate(object_location, dir_len);
if (git_buf_grow(object_location, dir_len + GIT_OID_HEXSZ + 2) < 0)
if (git_buf_grow(object_location, alloc_len) < 0)
return -1;
git_oid_pathfmt(object_location->ptr + dir_len, res_oid);
......@@ -930,15 +932,15 @@ int git_odb_backend_loose(
unsigned int file_mode)
{
loose_backend *backend;
size_t objects_dirlen;
size_t objects_dirlen, alloclen;
assert(backend_out && objects_dir);
objects_dirlen = strlen(objects_dir);
GITERR_CHECK_ALLOC_ADD(sizeof(loose_backend), objects_dirlen);
GITERR_CHECK_ALLOC_ADD(sizeof(loose_backend) + objects_dirlen, 2);
backend = git__calloc(1, sizeof(loose_backend) + objects_dirlen + 2);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(loose_backend), objects_dirlen);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 2);
backend = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(backend);
backend->parent.version = GIT_ODB_BACKEND_VERSION;
......
......@@ -38,6 +38,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
struct memory_packer_db *db = (struct memory_packer_db *)_backend;
struct memobject *obj = NULL;
khiter_t pos;
size_t alloc_len;
int rval;
pos = kh_put(oid, db->objects, oid, &rval);
......@@ -47,8 +48,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
if (rval == 0)
return 0;
GITERR_CHECK_ALLOC_ADD(sizeof(struct memobject), len);
obj = git__malloc(sizeof(struct memobject) + len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len);
obj = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(obj);
memcpy(obj->data, data, len);
......
......@@ -202,9 +202,8 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
return 0;
if (pb->nr_objects >= pb->nr_alloc) {
GITERR_CHECK_ALLOC_ADD(pb->nr_alloc, 1024);
GITERR_CHECK_ALLOC_MULTIPLY(pb->nr_alloc + 1024, 3 / 2);
newsize = (pb->nr_alloc + 1024) * 3 / 2;
GITERR_CHECK_ALLOC_ADD(&newsize, pb->nr_alloc, 1024);
GITERR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2);
if (!git__is_uint32(newsize)) {
giterr_set(GITERR_NOMEMORY, "Packfile too large to fit in memory.");
......@@ -833,7 +832,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
trg_object->delta_data = NULL;
}
if (delta_cacheable(pb, src_size, trg_size, delta_size)) {
if (!git__add_uint64_overflow(&pb->delta_cache_size, pb->delta_cache_size, delta_size))
if (git__add_uint64_overflow(&pb->delta_cache_size, pb->delta_cache_size, delta_size))
return -1;
git_packbuilder__cache_unlock(pb);
......
......@@ -624,7 +624,7 @@ int git_packfile_unpack(
struct pack_chain_elem *elem = NULL, *stack;
git_pack_cache_entry *cached = NULL;
struct pack_chain_elem small_stack[SMALL_STACK_SIZE];
size_t stack_size = 0, elem_pos;
size_t stack_size = 0, elem_pos, alloclen;
git_otype base_type;
/*
......@@ -684,8 +684,8 @@ int git_packfile_unpack(
if (cached && stack_size == 1) {
void *data = obj->data;
GITERR_CHECK_ALLOC_ADD(obj->len, 1);
obj->data = git__malloc(obj->len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, obj->len, 1);
obj->data = git__malloc(alloclen);
GITERR_CHECK_ALLOC(obj->data);
memcpy(obj->data, data, obj->len + 1);
......@@ -840,17 +840,18 @@ int packfile_unpack_compressed(
size_t size,
git_otype type)
{
size_t buf_size;
int st;
z_stream stream;
unsigned char *buffer, *in;
GITERR_CHECK_ALLOC_ADD(size, 1);
buffer = git__calloc(1, size + 1);
GITERR_CHECK_ALLOC_ADD(&buf_size, size, 1);
buffer = git__calloc(1, buf_size);
GITERR_CHECK_ALLOC(buffer);
memset(&stream, 0, sizeof(stream));
stream.next_out = buffer;
stream.avail_out = (uInt)size + 1;
stream.avail_out = (uInt)buf_size;
stream.zalloc = use_git_alloc;
stream.zfree = use_git_free;
......@@ -1089,17 +1090,17 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
{
struct stat st;
struct git_pack_file *p;
size_t path_len = path ? strlen(path) : 0;
size_t path_len = path ? strlen(path) : 0, alloc_len;
*pack_out = NULL;
if (path_len < strlen(".idx"))
return git_odb__error_notfound("invalid packfile path", NULL);
GITERR_CHECK_ALLOC_ADD(sizeof(*p), path_len);
GITERR_CHECK_ALLOC_ADD(sizeof(*p) + path_len, 2);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*p), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
p = git__calloc(1, sizeof(*p) + path_len + 2);
p = git__calloc(1, alloc_len);
GITERR_CHECK_ALLOC(p);
memcpy(p->pack_name, path, path_len + 1);
......
......@@ -620,11 +620,12 @@ static bool _check_dir_contents(
bool result;
size_t dir_size = git_buf_len(dir);
size_t sub_size = strlen(sub);
size_t alloc_size;
/* leave base valid even if we could not make space for subdir */
if (GIT_ALLOC_OVERFLOW_ADD(dir_size, sub_size) ||
GIT_ALLOC_OVERFLOW_ADD(dir_size + sub_size, 2) ||
git_buf_try_grow(dir, dir_size + sub_size + 2, false, false) < 0)
if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, dir_size, sub_size) ||
GIT_ADD_SIZET_OVERFLOW(&alloc_size, alloc_size, 2) ||
git_buf_try_grow(dir, alloc_size, false, false) < 0)
return false;
/* save excursion */
......@@ -786,7 +787,7 @@ int git_path_cmp(
int git_path_make_relative(git_buf *path, const char *parent)
{
const char *p, *q, *p_dirsep, *q_dirsep;
size_t plen = path->size, newlen, depth = 1, i, offset;
size_t plen = path->size, newlen, alloclen, depth = 1, i, offset;
for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) {
if (*p == '/' && *q == '/') {
......@@ -824,14 +825,14 @@ int git_path_make_relative(git_buf *path, const char *parent)
for (; (q = strchr(q, '/')) && *(q + 1); q++)
depth++;
GITERR_CHECK_ALLOC_MULTIPLY(depth, 3);
GITERR_CHECK_ALLOC_ADD(depth * 3, plen);
GITERR_CHECK_ALLOC_ADD(depth * 3, 1);
newlen = (depth * 3) + plen;
GITERR_CHECK_ALLOC_MULTIPLY(&newlen, depth, 3);
GITERR_CHECK_ALLOC_ADD(&newlen, newlen, plen);
GITERR_CHECK_ALLOC_ADD(&alloclen, newlen, 1);
/* save the offset as we might realllocate the pointer */
offset = p - path->ptr;
if (git_buf_try_grow(path, newlen + 1, 1, 0) < 0)
if (git_buf_try_grow(path, alloclen, 1, 0) < 0)
return -1;
p = path->ptr + offset;
......@@ -876,7 +877,7 @@ void git_path_iconv_clear(git_path_iconv_t *ic)
int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen)
{
char *nfd = *in, *nfc;
size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, rv;
size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, alloclen, rv;
int retry = 1;
if (!ic || ic->map == (iconv_t)-1 ||
......@@ -886,8 +887,8 @@ int git_path_iconv(git_path_iconv_t *ic, char **in, size_t *inlen)
git_buf_clear(&ic->buf);
while (1) {
GITERR_CHECK_ALLOC_ADD(wantlen, 1);
if (git_buf_grow(&ic->buf, wantlen + 1) < 0)
GITERR_CHECK_ALLOC_ADD(&alloclen, wantlen, 1);
if (git_buf_grow(&ic->buf, alloclen) < 0)
return -1;
nfc = ic->buf.ptr + ic->buf.size;
......@@ -1072,21 +1073,13 @@ static int entry_path_alloc(
size_t alloc_extra)
{
int need_slash = (path_len > 0 && path[path_len-1] != '/') ? 1 : 0;
size_t alloc_size = path_len;
size_t alloc_size;
char *entry_path;
GITERR_CHECK_ALLOC_ADD(alloc_size, de_len);
alloc_size += de_len;
GITERR_CHECK_ALLOC_ADD(alloc_size, need_slash);
alloc_size += need_slash;
GITERR_CHECK_ALLOC_ADD(alloc_size, 1);
alloc_size++;
GITERR_CHECK_ALLOC_ADD(alloc_size, alloc_extra);
alloc_size += alloc_extra;
GITERR_CHECK_ALLOC_ADD(&alloc_size, path_len, de_len);
GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, need_slash);
GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, 1);
GITERR_CHECK_ALLOC_ADD(&alloc_size, alloc_size, alloc_extra);
entry_path = git__calloc(1, alloc_size);
GITERR_CHECK_ALLOC(entry_path);
......
......@@ -107,21 +107,22 @@ static void pool_insert_page(git_pool *pool, git_pool_page *page)
static void *pool_alloc_page(git_pool *pool, uint32_t size)
{
git_pool_page *page;
uint32_t alloc_size;
uint32_t new_page_size;
size_t alloc_size;
if (size <= pool->page_size)
alloc_size = pool->page_size;
new_page_size = pool->page_size;
else {
alloc_size = size;
new_page_size = size;
pool->has_large_page_alloc = 1;
}
if (GIT_ALLOC_OVERFLOW_ADD(alloc_size, sizeof(git_pool_page)) ||
!(page = git__calloc(1, alloc_size + sizeof(git_pool_page))))
if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
!(page = git__calloc(1, alloc_size)))
return NULL;
page->size = alloc_size;
page->avail = alloc_size - size;
page->size = new_page_size;
page->avail = new_page_size - size;
if (page->avail > 0)
pool_insert_page(pool, page);
......
......@@ -36,15 +36,13 @@ enum {
static git_reference *alloc_ref(const char *name)
{
git_reference *ref;
size_t namelen = strlen(name), reflen = sizeof(git_reference);
if (GIT_ALLOC_OVERFLOW_ADD(reflen, namelen) ||
GIT_ALLOC_OVERFLOW_ADD(reflen + namelen, 1) ||
(ref = git__calloc(1, reflen + namelen + 1)) == NULL)
return NULL;
git_reference *ref = NULL;
size_t namelen = strlen(name), reflen;
memcpy(ref->name, name, namelen + 1);
if (!GIT_ADD_SIZET_OVERFLOW(&reflen, sizeof(git_reference), namelen) &&
!GIT_ADD_SIZET_OVERFLOW(&reflen, reflen, 1) &&
(ref = git__calloc(1, reflen)) != NULL)
memcpy(ref->name, name, namelen + 1);
return ref;
}
......@@ -96,12 +94,12 @@ git_reference *git_reference__set_name(
git_reference *ref, const char *name)
{
size_t namelen = strlen(name);
size_t reflen = sizeof(git_reference);
size_t reflen;
git_reference *rewrite = NULL;
if (!GIT_ALLOC_OVERFLOW_ADD(reflen, namelen) &&
!GIT_ALLOC_OVERFLOW_ADD(reflen + namelen, 1) &&
(rewrite = git__realloc(ref, reflen + namelen + 1)) != NULL)
if (!GIT_ADD_SIZET_OVERFLOW(&reflen, sizeof(git_reference), namelen) &&
!GIT_ADD_SIZET_OVERFLOW(&reflen, reflen, 1) &&
(rewrite = git__realloc(ref, reflen)) != NULL)
memcpy(rewrite->name, name, namelen + 1);
return rewrite;
......
......@@ -11,13 +11,13 @@ int git_sortedcache_new(
const char *path)
{
git_sortedcache *sc;
size_t pathlen;
size_t pathlen, alloclen;
pathlen = path ? strlen(path) : 0;
GITERR_CHECK_ALLOC_ADD(sizeof(git_sortedcache), pathlen);
GITERR_CHECK_ALLOC_ADD(sizeof(git_sortedcache) + pathlen, 1);
sc = git__calloc(1, sizeof(git_sortedcache) + pathlen + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_sortedcache), pathlen);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
sc = git__calloc(1, alloclen);
GITERR_CHECK_ALLOC(sc);
if (git_pool_init(&sc->pool, 1, 0) < 0 ||
......
......@@ -72,7 +72,7 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
};
unsigned int i;
size_t text_len;
size_t text_len, alloc_len;
char *search;
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
......@@ -117,8 +117,8 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
text_len = search - buffer;
GITERR_CHECK_ALLOC_ADD(text_len, 1);
tag->tag_name = git__malloc(text_len + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_len, text_len, 1);
tag->tag_name = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(tag->tag_name);
memcpy(tag->tag_name, buffer, text_len);
......@@ -142,8 +142,8 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
text_len = buffer_end - ++buffer;
GITERR_CHECK_ALLOC_ADD(text_len, 1);
tag->message = git__malloc(text_len + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_len, text_len, 1);
tag->message = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(tag->message);
memcpy(tag->message, buffer, text_len);
......
......@@ -306,15 +306,15 @@ int git_cred_default_new(git_cred **cred)
int git_cred_username_new(git_cred **cred, const char *username)
{
git_cred_username *c;
size_t len;
size_t len, allocsize;
assert(cred);
len = strlen(username);
GITERR_CHECK_ALLOC_ADD(sizeof(git_cred_username), len);
GITERR_CHECK_ALLOC_ADD(sizeof(git_cred_username) + len, 1);
c = git__malloc(sizeof(git_cred_username) + len + 1);
GITERR_CHECK_ALLOC_ADD(&allocsize, sizeof(git_cred_username), len);
GITERR_CHECK_ALLOC_ADD(&allocsize, allocsize, 1);
c = git__malloc(allocsize);
GITERR_CHECK_ALLOC(c);
c->parent.credtype = GIT_CREDTYPE_USERNAME;
......
......@@ -102,10 +102,11 @@ static int pack_pkt(git_pkt **out)
static int comment_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_comment *pkt;
size_t alloclen;
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_comment), len);
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_comment) + len, 1);
pkt = git__malloc(sizeof(git_pkt_comment) + len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_comment), len);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
pkt = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_COMMENT;
......@@ -120,14 +121,15 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
static int err_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_err *pkt;
size_t alloclen;
/* Remove "ERR " from the line */
line += 4;
len -= 4;
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_progress), len);
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_progress) + len, 1);
pkt = git__malloc(sizeof(git_pkt_err) + len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
pkt = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_ERR;
......@@ -143,12 +145,13 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
static int data_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_data *pkt;
size_t alloclen;
line++;
len--;
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_progress), len);
pkt = git__malloc(sizeof(git_pkt_data) + len);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
pkt = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_DATA;
......@@ -163,12 +166,13 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_progress *pkt;
size_t alloclen;
line++;
len--;
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_progress), len);
pkt = git__malloc(sizeof(git_pkt_progress) + len);
GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(git_pkt_progress), len);
pkt = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_PROGRESS;
......@@ -183,13 +187,14 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_err *pkt;
size_t alloc_len;
line++;
len--;
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_err), len);
GITERR_CHECK_ALLOC_ADD(sizeof(git_pkt_err) + len, 1);
pkt = git__malloc(sizeof(git_pkt_err) + len + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(git_pkt_err), len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 1);
pkt = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_ERR;
......@@ -209,6 +214,7 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
{
int error;
git_pkt_ref *pkt;
size_t alloclen;
pkt = git__malloc(sizeof(git_pkt_ref));
GITERR_CHECK_ALLOC(pkt);
......@@ -232,8 +238,8 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
if (line[len - 1] == '\n')
--len;
GITERR_CHECK_ALLOC_ADD(len, 1);
pkt->head.name = git__malloc(len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, len, 1);
pkt->head.name = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt->head.name);
memcpy(pkt->head.name, line, len);
......@@ -255,6 +261,7 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_ok *pkt;
const char *ptr;
size_t alloc_len;
pkt = git__malloc(sizeof(*pkt));
GITERR_CHECK_ALLOC(pkt);
......@@ -268,8 +275,8 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
}
len = ptr - line;
GITERR_CHECK_ALLOC_ADD(len, 1);
pkt->ref = git__malloc(len + 1);
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
pkt->ref = git__malloc(alloc_len);
GITERR_CHECK_ALLOC(pkt->ref);
memcpy(pkt->ref, line, len);
......@@ -283,6 +290,7 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_ng *pkt;
const char *ptr;
size_t alloclen;
pkt = git__malloc(sizeof(*pkt));
GITERR_CHECK_ALLOC(pkt);
......@@ -296,8 +304,8 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
}
len = ptr - line;
GITERR_CHECK_ALLOC_ADD(len, 1);
pkt->ref = git__malloc(len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, len, 1);
pkt->ref = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt->ref);
memcpy(pkt->ref, line, len);
......@@ -310,8 +318,8 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
}
len = ptr - line;
GITERR_CHECK_ALLOC_ADD(len, 1);
pkt->msg = git__malloc(len + 1);
GITERR_CHECK_ALLOC_ADD(&alloclen, len, 1);
pkt->msg = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt->msg);
memcpy(pkt->msg, line, len);
......
......@@ -84,12 +84,11 @@ int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
static git_tree_entry *alloc_entry(const char *filename)
{
git_tree_entry *entry = NULL;
size_t filename_len = strlen(filename),
tree_len = sizeof(git_tree_entry);
size_t filename_len = strlen(filename), tree_len;
if (GIT_ALLOC_OVERFLOW_ADD(tree_len, filename_len) ||
GIT_ALLOC_OVERFLOW_ADD(tree_len + filename_len, 1) ||
!(entry = git__malloc(tree_len + filename_len + 1)))
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
!(entry = git__malloc(tree_len)))
return NULL;
memset(entry, 0x0, sizeof(git_tree_entry));
......@@ -207,16 +206,13 @@ void git_tree_entry_free(git_tree_entry *entry)
int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
{
size_t total_size = sizeof(git_tree_entry);
size_t total_size;
git_tree_entry *copy;
assert(source);
GITERR_CHECK_ALLOC_ADD(total_size, source->filename_len);
total_size += source->filename_len;
GITERR_CHECK_ALLOC_ADD(total_size, 1);
total_size++;
GITERR_CHECK_ALLOC_ADD(&total_size, sizeof(git_tree_entry), source->filename_len);
GITERR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
copy = git__malloc(total_size);
GITERR_CHECK_ALLOC(copy);
......
......@@ -59,17 +59,13 @@ GIT_INLINE(char *) git__strdup(const char *str)
GIT_INLINE(char *) git__strndup(const char *str, size_t n)
{
size_t length = 0;
size_t length = 0, alloclength;
char *ptr;
length = p_strnlen(str, n);
if (GIT_ALLOC_OVERFLOW_ADD(length, 1))
return NULL;
ptr = git__malloc(length + 1);
if (!ptr)
if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
!(ptr = git__malloc(alloclength)))
return NULL;
if (length)
......@@ -84,8 +80,10 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
GIT_INLINE(char *) git__substrdup(const char *start, size_t n)
{
char *ptr;
size_t alloclen;
if (GIT_ALLOC_OVERFLOW_ADD(n, 1) || !(ptr = git__malloc(n+1)))
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
!(ptr = git__malloc(alloclen)))
return NULL;
memcpy(ptr, start, n);
......@@ -107,8 +105,9 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
*/
GIT_INLINE(void *) git__reallocarray(void *ptr, size_t nelem, size_t elsize)
{
return GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize) ?
NULL : realloc(ptr, nelem * elsize);
size_t newsize;
return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ?
NULL : realloc(ptr, newsize);
}
/**
......
......@@ -46,8 +46,7 @@ int git_vector_dup(git_vector *v, const git_vector *src, git_vector_cmp cmp)
assert(v && src);
GITERR_CHECK_ALLOC_MULTIPLY(src->length, sizeof(void *));
bytes = src->length * sizeof(void *);
GITERR_CHECK_ALLOC_MULTIPLY(&bytes, src->length, sizeof(void *));
v->_alloc_size = src->length;
v->_cmp = cmp ? cmp : src->_cmp;
......
......@@ -11,16 +11,16 @@ git__DIR *git__opendir(const char *dir)
{
git_win32_path filter_w;
git__DIR *new = NULL;
size_t dirlen;
size_t dirlen, alloclen;
if (!dir || !git_win32__findfirstfile_filter(filter_w, dir))
return NULL;
dirlen = strlen(dir);
if (GIT_ALLOC_OVERFLOW_ADD(sizeof(*new), dirlen) ||
GIT_ALLOC_OVERFLOW_ADD(sizeof(*new) + dirlen, 1) ||
!(new = git__calloc(1, sizeof(*new) + dirlen + 1)))
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, sizeof(*new), dirlen) ||
GIT_ADD_SIZET_OVERFLOW(&alloclen, alloclen, 1) ||
!(new = git__calloc(1, alloclen)))
return NULL;
memcpy(new->dir, dir, dirlen);
......
......@@ -112,7 +112,8 @@ void test_core_errors__restore(void)
static int test_arraysize_multiply(size_t nelem, size_t size)
{
GITERR_CHECK_ALLOC_MULTIPLY(nelem, size);
size_t out;
GITERR_CHECK_ALLOC_MULTIPLY(&out, nelem, size);
return 0;
}
......@@ -133,7 +134,8 @@ void test_core_errors__integer_overflow_alloc_multiply(void)
static int test_arraysize_add(size_t one, size_t two)
{
GITERR_CHECK_ALLOC_ADD(one, two);
size_t out;
GITERR_CHECK_ALLOC_ADD(&out, one, two);
return 0;
}
......@@ -152,21 +154,23 @@ void test_core_errors__integer_overflow_alloc_add(void)
void test_core_errors__integer_overflow_sets_oom(void)
{
size_t out;
giterr_clear();
cl_assert(!GIT_ALLOC_OVERFLOW_ADD(SIZE_MAX-1, 1));
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX-1, 1));
cl_assert_equal_p(NULL, giterr_last());
giterr_clear();
cl_assert(!GIT_ALLOC_OVERFLOW_ADD(42, 69));
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, 42, 69));
cl_assert_equal_p(NULL, giterr_last());
giterr_clear();
cl_assert(GIT_ALLOC_OVERFLOW_ADD(SIZE_MAX, SIZE_MAX));
cl_assert(GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX, SIZE_MAX));
cl_assert_equal_i(GITERR_NOMEMORY, giterr_last()->klass);
cl_assert_equal_s("Out of memory", giterr_last()->message);
giterr_clear();
cl_assert(GIT_ALLOC_OVERFLOW_MULTIPLY(SIZE_MAX, SIZE_MAX));
cl_assert(GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX, SIZE_MAX));
cl_assert_equal_i(GITERR_NOMEMORY, giterr_last()->klass);
cl_assert_equal_s("Out of memory", giterr_last()->message);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment