85 lines
2.7 KiB
Diff
85 lines
2.7 KiB
Diff
|
From 369e8477d25132e9eeefb89ae1dacb3c4a738652 Mon Sep 17 00:00:00 2001
|
||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||
|
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 <assert.h>
|
||
|
+#include <limits.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
@@ -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);
|