Commit 2884cc42 by Edward Thomson Committed by Edward Thomson

overflow checking: don't make callers set oom

Have the ALLOC_OVERFLOW testing macros also simply set_oom in the
case where a computation would overflow, so that callers don't
need to.
parent 4aa664ae
...@@ -105,7 +105,6 @@ int git_buf_grow_by(git_buf *buffer, size_t additional_size) ...@@ -105,7 +105,6 @@ int git_buf_grow_by(git_buf *buffer, size_t additional_size)
{ {
if (GIT_ALLOC_OVERFLOW_ADD(buffer->size, additional_size)) { if (GIT_ALLOC_OVERFLOW_ADD(buffer->size, additional_size)) {
buffer->ptr = git_buf__oom; buffer->ptr = git_buf__oom;
giterr_set_oom();
return -1; return -1;
} }
......
...@@ -176,25 +176,19 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v ...@@ -176,25 +176,19 @@ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int v
/** Check for integer overflow from addition or multiplication */ /** Check for integer overflow from addition or multiplication */
#define GIT_ALLOC_OVERFLOW_ADD(one, two) \ #define GIT_ALLOC_OVERFLOW_ADD(one, two) \
((one) + (two) < (one)) (((one) + (two) < (one)) ? (giterr_set_oom(), 1) : 0)
/** Check for integer overflow from multiplication */ /** Check for integer overflow from multiplication */
#define GIT_ALLOC_OVERFLOW_MULTIPLY(one, two) \ #define GIT_ALLOC_OVERFLOW_MULTIPLY(one, two) \
(one && ((one) * (two)) / (one) != (two)) ((one && ((one) * (two)) / (one) != (two)) ? (giterr_set_oom(), 1) : 0)
/** Check for additive overflow, failing if it would occur. */ /** Check for additive overflow, failing if it would occur. */
#define GITERR_CHECK_ALLOC_ADD(one, two) \ #define GITERR_CHECK_ALLOC_ADD(one, two) \
if (GIT_ALLOC_OVERFLOW_ADD(one, two)) { \ if (GIT_ALLOC_OVERFLOW_ADD(one, two)) { return -1; }
giterr_set_oom(); \
return -1; \
}
/** Check for multiplicative overflow, failing if it would occur. */ /** Check for multiplicative overflow, failing if it would occur. */
#define GITERR_CHECK_ALLOC_MULTIPLY(nelem, elsize) \ #define GITERR_CHECK_ALLOC_MULTIPLY(nelem, elsize) \
if (GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize)) { \ if (GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize)) { return -1; }
giterr_set_oom(); \
return -1; \
}
/* NOTE: other giterr functions are in the public errors.h header file */ /* NOTE: other giterr functions are in the public errors.h header file */
......
...@@ -905,7 +905,6 @@ static char *reader_readline(struct reader *reader, bool skip_whitespace) ...@@ -905,7 +905,6 @@ static char *reader_readline(struct reader *reader, bool skip_whitespace)
if (GIT_ALLOC_OVERFLOW_ADD(line_len, 1) || if (GIT_ALLOC_OVERFLOW_ADD(line_len, 1) ||
(line = git__malloc(line_len + 1)) == NULL) { (line = git__malloc(line_len + 1)) == NULL) {
giterr_set_oom();
return NULL; return NULL;
} }
...@@ -1620,7 +1619,6 @@ static char *fixup_line(const char *ptr, int quote_count) ...@@ -1620,7 +1619,6 @@ static char *fixup_line(const char *ptr, int quote_count)
if (GIT_ALLOC_OVERFLOW_ADD(ptr_len, 1) || if (GIT_ALLOC_OVERFLOW_ADD(ptr_len, 1) ||
(str = git__malloc(ptr_len + 1)) == NULL) { (str = git__malloc(ptr_len + 1)) == NULL) {
giterr_set_oom();
return NULL; return NULL;
} }
......
...@@ -138,7 +138,7 @@ static int lookup_index_alloc( ...@@ -138,7 +138,7 @@ static int lookup_index_alloc(
index_len += hash_len; index_len += hash_len;
if (!git__is_ulong(index_len)) { if (!git__is_ulong(index_len)) {
giterr_set_oom(); giterr_set(GITERR_NOMEMORY, "Overly large delta");
return -1; return -1;
} }
......
...@@ -833,10 +833,8 @@ static git_index_reuc_entry *reuc_entry_alloc(const char *path) ...@@ -833,10 +833,8 @@ static git_index_reuc_entry *reuc_entry_alloc(const char *path)
struct reuc_entry_internal *entry; struct reuc_entry_internal *entry;
if (GIT_ALLOC_OVERFLOW_ADD(structlen, pathlen) || if (GIT_ALLOC_OVERFLOW_ADD(structlen, pathlen) ||
GIT_ALLOC_OVERFLOW_ADD(structlen + pathlen, 1)) { GIT_ALLOC_OVERFLOW_ADD(structlen + pathlen, 1))
giterr_set_oom();
return NULL; return NULL;
}
entry = git__calloc(1, structlen + pathlen + 1); entry = git__calloc(1, structlen + pathlen + 1);
if (!entry) if (!entry)
......
...@@ -504,10 +504,8 @@ static git_pobject **compute_write_order(git_packbuilder *pb) ...@@ -504,10 +504,8 @@ static git_pobject **compute_write_order(git_packbuilder *pb)
unsigned int i, wo_end, last_untagged; unsigned int i, wo_end, last_untagged;
git_pobject **wo; git_pobject **wo;
if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL) { if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL)
giterr_set_oom();
return NULL; return NULL;
}
for (i = 0; i < pb->nr_objects; i++) { for (i = 0; i < pb->nr_objects; i++) {
git_pobject *po = pb->object_list + i; git_pobject *po = pb->object_list + i;
......
...@@ -117,10 +117,8 @@ static void *pool_alloc_page(git_pool *pool, uint32_t size) ...@@ -117,10 +117,8 @@ static void *pool_alloc_page(git_pool *pool, uint32_t size)
} }
if (GIT_ALLOC_OVERFLOW_ADD(alloc_size, sizeof(git_pool_page)) || if (GIT_ALLOC_OVERFLOW_ADD(alloc_size, sizeof(git_pool_page)) ||
!(page = git__calloc(1, alloc_size + sizeof(git_pool_page)))) { !(page = git__calloc(1, alloc_size + sizeof(git_pool_page))))
giterr_set_oom();
return NULL; return NULL;
}
page->size = alloc_size; page->size = alloc_size;
page->avail = alloc_size - size; page->avail = alloc_size - size;
......
...@@ -41,10 +41,8 @@ static git_reference *alloc_ref(const char *name) ...@@ -41,10 +41,8 @@ static git_reference *alloc_ref(const char *name)
if (GIT_ALLOC_OVERFLOW_ADD(reflen, namelen) || if (GIT_ALLOC_OVERFLOW_ADD(reflen, namelen) ||
GIT_ALLOC_OVERFLOW_ADD(reflen + namelen, 1) || GIT_ALLOC_OVERFLOW_ADD(reflen + namelen, 1) ||
(ref = git__calloc(1, reflen + namelen + 1)) == NULL) { (ref = git__calloc(1, reflen + namelen + 1)) == NULL)
giterr_set_oom();
return NULL; return NULL;
}
memcpy(ref->name, name, namelen + 1); memcpy(ref->name, name, namelen + 1);
......
...@@ -89,10 +89,8 @@ static git_tree_entry *alloc_entry(const char *filename) ...@@ -89,10 +89,8 @@ static git_tree_entry *alloc_entry(const char *filename)
if (GIT_ALLOC_OVERFLOW_ADD(tree_len, filename_len) || if (GIT_ALLOC_OVERFLOW_ADD(tree_len, filename_len) ||
GIT_ALLOC_OVERFLOW_ADD(tree_len + filename_len, 1) || GIT_ALLOC_OVERFLOW_ADD(tree_len + filename_len, 1) ||
!(entry = git__malloc(tree_len + filename_len + 1))) { !(entry = git__malloc(tree_len + filename_len + 1)))
giterr_set_oom();
return NULL; return NULL;
}
memset(entry, 0x0, sizeof(git_tree_entry)); memset(entry, 0x0, sizeof(git_tree_entry));
memcpy(entry->filename, filename, filename_len); memcpy(entry->filename, filename, filename_len);
......
...@@ -64,10 +64,8 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n) ...@@ -64,10 +64,8 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
length = p_strnlen(str, n); length = p_strnlen(str, n);
if (GIT_ALLOC_OVERFLOW_ADD(length, 1)) { if (GIT_ALLOC_OVERFLOW_ADD(length, 1))
giterr_set_oom();
return NULL; return NULL;
}
ptr = git__malloc(length + 1); ptr = git__malloc(length + 1);
...@@ -87,10 +85,8 @@ GIT_INLINE(char *) git__substrdup(const char *start, size_t n) ...@@ -87,10 +85,8 @@ GIT_INLINE(char *) git__substrdup(const char *start, size_t n)
{ {
char *ptr; char *ptr;
if (GIT_ALLOC_OVERFLOW_ADD(n, 1) || !(ptr = git__malloc(n+1))) { if (GIT_ALLOC_OVERFLOW_ADD(n, 1) || !(ptr = git__malloc(n+1)))
giterr_set_oom();
return NULL; return NULL;
}
memcpy(ptr, start, n); memcpy(ptr, start, n);
ptr[n] = '\0'; ptr[n] = '\0';
...@@ -111,11 +107,8 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size) ...@@ -111,11 +107,8 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
*/ */
GIT_INLINE(void *) git__reallocarray(void *ptr, size_t nelem, size_t elsize) GIT_INLINE(void *) git__reallocarray(void *ptr, size_t nelem, size_t elsize)
{ {
void *new_ptr = NULL; return GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize) ?
if (GIT_ALLOC_OVERFLOW_MULTIPLY(nelem, elsize) || NULL : realloc(ptr, nelem * elsize);
!(new_ptr = realloc(ptr, nelem * elsize)))
giterr_set_oom();
return new_ptr;
} }
/** /**
......
...@@ -20,10 +20,8 @@ git__DIR *git__opendir(const char *dir) ...@@ -20,10 +20,8 @@ git__DIR *git__opendir(const char *dir)
if (GIT_ALLOC_OVERFLOW_ADD(sizeof(*new), dirlen) || if (GIT_ALLOC_OVERFLOW_ADD(sizeof(*new), dirlen) ||
GIT_ALLOC_OVERFLOW_ADD(sizeof(*new) + dirlen, 1) || GIT_ALLOC_OVERFLOW_ADD(sizeof(*new) + dirlen, 1) ||
!(new = git__calloc(1, sizeof(*new) + dirlen + 1))) { !(new = git__calloc(1, sizeof(*new) + dirlen + 1)))
giterr_set_oom();
return NULL; return NULL;
}
memcpy(new->dir, dir, dirlen); memcpy(new->dir, dir, dirlen);
......
...@@ -149,3 +149,24 @@ void test_core_errors__integer_overflow_alloc_add(void) ...@@ -149,3 +149,24 @@ void test_core_errors__integer_overflow_alloc_add(void)
cl_assert_equal_i(GITERR_NOMEMORY, giterr_last()->klass); cl_assert_equal_i(GITERR_NOMEMORY, giterr_last()->klass);
cl_assert_equal_s("Out of memory", giterr_last()->message); cl_assert_equal_s("Out of memory", giterr_last()->message);
} }
void test_core_errors__integer_overflow_sets_oom(void)
{
giterr_clear();
cl_assert(!GIT_ALLOC_OVERFLOW_ADD(SIZE_MAX-1, 1));
cl_assert_equal_p(NULL, giterr_last());
giterr_clear();
cl_assert(!GIT_ALLOC_OVERFLOW_ADD(42, 69));
cl_assert_equal_p(NULL, giterr_last());
giterr_clear();
cl_assert(GIT_ALLOC_OVERFLOW_ADD(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_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