From 7d358f2e4cc343948beb6b0a2314d6333ff0ba93 Mon Sep 17 00:00:00 2001 From: hanjinpeng Date: Mon, 14 Sep 2026 11:47:43 -0400 Subject: [PATCH] arraylist: reject negative indices and size overflow - array_list_get_idx() did not reject a negative index, so a negative argument read before the start of the backing array. - array_list_put_idx() passed idx unchecked to array_list_expand_internal() as idx + 1, and the expansion did new_size = arr->size << 1 and new_size * sizeof(void*). A negative index wrote out of bounds and a very large one overflowed the signed arithmetic (both flagged by ASan/UBSan). Reject a negative or INT_MAX index in put_idx and a negative index in get_idx, and cap the growth so neither the doubling nor the byte-size computation can overflow. --- arraylist.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) 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;