diff --git a/arraylist.c b/arraylist.c index bab903e..571b0ab 100644 --- a/arraylist.c +++ b/arraylist.c @@ -19,6 +19,8 @@ # include #endif /* HAVE_STRINGS_H */ +#include + #include "arraylist.h" struct array_list* @@ -51,22 +53,32 @@ array_list_free(struct array_list *arr) void* array_list_get_idx(struct array_list *arr, int i) { - if(i >= arr->length) return NULL; + if(i < 0 || i >= arr->length) return NULL; return arr->array[i]; } +/* the largest element count whose byte size fits in an int-sized index space */ +#define ARRAY_LIST_MAX_ELEMS ((int)(INT_MAX / sizeof(void*))) + static int array_list_expand_internal(struct array_list *arr, int max) { void *t; int new_size; if(max < arr->size) return 0; - new_size = arr->size << 1; - if (new_size < max) + /* Refuse sizes that would overflow when doubled or when converted to a + * byte count. */ + if(max > ARRAY_LIST_MAX_ELEMS) return -1; + if(arr->size > ARRAY_LIST_MAX_ELEMS / 2) { new_size = max; - if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; + } else { + new_size = arr->size << 1; + if (new_size < max) + new_size = max; + } + if(!(t = realloc(arr->array, (size_t)new_size*sizeof(void*)))) return -1; arr->array = (void**)t; - (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); + (void)memset(arr->array + arr->size, 0, (size_t)(new_size-arr->size)*sizeof(void*)); arr->size = new_size; return 0; } @@ -74,6 +86,9 @@ static int array_list_expand_internal(struct array_list *arr, int max) int array_list_put_idx(struct array_list *arr, int idx, void *data) { + /* reject a negative index (heap underflow) and an index whose +1 would + * overflow int */ + if(idx < 0 || idx == INT_MAX) return -1; if(array_list_expand_internal(arr, idx+1)) return -1; if(arr->array[idx]) arr->free_fn(arr->array[idx]); arr->array[idx] = data;