summaryrefslogtreecommitdiff
path: root/src/array.h
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-02-09 23:41:13 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2015-02-12 22:54:46 -0500
commit392702ee2c88d7d8aaff25f7a84acb73606f9094 (patch)
tree97a66fe6e488797c6a9c2680ccb31964f61fe340 /src/array.h
parentd24a5312d8ab6d3cdb259e450ec9f1e2e6f3399d (diff)
downloadlibgit2-392702ee2c88d7d8aaff25f7a84acb73606f9094.tar.gz
allocations: test for overflow of requested size
Introduce some helper macros to test integer overflow from arithmetic and set error message appropriately.
Diffstat (limited to 'src/array.h')
-rw-r--r--src/array.h27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/array.h b/src/array.h
index af9eafa43..ca5a35ffe 100644
--- a/src/array.h
+++ b/src/array.h
@@ -45,15 +45,28 @@ typedef git_array_t(char) git_array_generic_t;
GIT_INLINE(void *) git_array_grow(void *_a, size_t item_size)
{
volatile git_array_generic_t *a = _a;
- uint32_t new_size = (a->size < 8) ? 8 : a->asize * 3 / 2;
- char *new_array = git__realloc(a->ptr, new_size * item_size);
- if (!new_array) {
- git_array_clear(*a);
- return NULL;
+ uint32_t new_size;
+ char *new_array;
+
+ if (a->size < 8) {
+ new_size = 8;
} else {
- a->ptr = new_array; a->asize = new_size; a->size++;
- return a->ptr + (a->size - 1) * item_size;
+ if (GIT_ALLOC_OVERFLOW_MULTIPLY(a->size, 3 / 2))
+ goto on_oom;
+
+ new_size = a->size * 3 / 2;
}
+
+ if (GIT_ALLOC_OVERFLOW_MULTIPLY(new_size, item_size) ||
+ (new_array = git__realloc(a->ptr, new_size * item_size)) == NULL)
+ goto on_oom;
+
+ a->ptr = new_array; a->asize = new_size; a->size++;
+ return a->ptr + (a->size - 1) * item_size;
+
+on_oom:
+ git_array_clear(*a);
+ return NULL;
}
#define git_array_alloc(a) \