From 369e8477d25132e9eeefb89ae1dacb3c4a738652 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Sat, 22 Aug 2020 12:06:15 +0200 Subject: [PATCH] Validate size arguments in arraylist functions. The array_list_new2 function, which is externally reachable through json_object_new_array_ext, does not check if specified initial size actually fits into memory on 32 bit architectures. It also allows negative values, which could lead to an overflow on these architectures as well. I have added test cases for these situations. While at it, also protect array_list_shrink against too large empty_slots argument. No test added because it takes a huge length value, therefore a lot of items within the array, to overflow the calculation. In theory this affects 64 bit sytems as well, but since the arraylist API is not supposed to be used by external applications according to its header file, the call is protected due to int limitation of json_object_array_shrink. --- arraylist.c | 4 ++++ tests/test1.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/arraylist.c b/arraylist.c index c21b8e1dfb..d8e12d11cb 100644 --- a/arraylist.c +++ b/arraylist.c @@ -45,6 +45,8 @@ struct array_list *array_list_new2(array_list_free_fn *free_fn, int initial_size { struct array_list *arr; + if (initial_size < 0 || (size_t)initial_size >= SIZE_T_MAX / sizeof(void *)) + return NULL; arr = (struct array_list *)malloc(sizeof(struct array_list)); if (!arr) return NULL; @@ -106,6 +108,8 @@ int array_list_shrink(struct array_list *arr, size_t empty_slots) void *t; size_t new_size; + if (empty_slots >= SIZE_T_MAX / sizeof(void *) - arr->length) + return -1; new_size = arr->length + empty_slots; if (new_size == arr->size) return 0; diff --git a/tests/test1.c b/tests/test1.c index 6682120cd9..7e41610561 100644 --- a/tests/test1.c +++ b/tests/test1.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -307,6 +308,27 @@ int main(int argc, char **argv) } printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object)); + json_object_put(my_array); + my_array = json_object_new_array_ext(INT_MIN + 1); + if (my_array != NULL) + { + printf("ERROR: able to allocate an array of negative size!\n"); + fflush(stdout); + json_object_put(my_array); + my_array = NULL; + } + +#if SIZEOF_SIZE_T == SIZEOF_INT + my_array = json_object_new_array_ext(INT_MAX / 2 + 2); + if (my_array != NULL) + { + printf("ERROR: able to allocate an array of insufficient size!\n"); + fflush(stdout); + json_object_put(my_array); + my_array = NULL; + } +#endif + json_object_put(my_string); json_object_put(my_int); json_object_put(my_null);