mirror of
https://github.com/json-c/json-c.git
synced 2026-03-22 14:39:07 +08:00
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.
340 lines
11 KiB
C
340 lines
11 KiB
C
#include <assert.h>
|
|
#include <limits.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "json.h"
|
|
#include "parse_flags.h"
|
|
|
|
static int sort_fn(const void *j1, const void *j2)
|
|
{
|
|
json_object *const *jso1, *const *jso2;
|
|
int i1, i2;
|
|
|
|
jso1 = (json_object *const *)j1;
|
|
jso2 = (json_object *const *)j2;
|
|
if (!*jso1 && !*jso2)
|
|
return 0;
|
|
if (!*jso1)
|
|
return -1;
|
|
if (!*jso2)
|
|
return 1;
|
|
|
|
i1 = json_object_get_int(*jso1);
|
|
i2 = json_object_get_int(*jso2);
|
|
|
|
return i1 - i2;
|
|
}
|
|
|
|
#ifdef TEST_FORMATTED
|
|
static const char *to_json_string(json_object *obj, int flags)
|
|
{
|
|
size_t length;
|
|
char *copy;
|
|
const char *result;
|
|
|
|
result = json_object_to_json_string_length(obj, flags, &length);
|
|
copy = strdup(result);
|
|
if (copy == NULL)
|
|
printf("to_json_string: Allocation failed!\n");
|
|
else
|
|
{
|
|
result = json_object_to_json_string_ext(obj, flags);
|
|
if (length != strlen(result))
|
|
printf("to_json_string: Length mismatch!\n");
|
|
if (strcmp(copy, result) != 0)
|
|
printf("to_json_string: Comparison Failed!\n");
|
|
free(copy);
|
|
}
|
|
return result;
|
|
}
|
|
#define json_object_to_json_string(obj) to_json_string(obj, sflags)
|
|
#else
|
|
/* no special define */
|
|
#endif
|
|
|
|
json_object *make_array(void);
|
|
json_object *make_array()
|
|
{
|
|
json_object *my_array;
|
|
|
|
my_array = json_object_new_array();
|
|
json_object_array_add(my_array, json_object_new_int(1));
|
|
json_object_array_add(my_array, json_object_new_int(2));
|
|
json_object_array_add(my_array, json_object_new_int(3));
|
|
json_object_array_put_idx(my_array, 4, json_object_new_int(5));
|
|
json_object_array_put_idx(my_array, 3, json_object_new_int(4));
|
|
json_object_array_put_idx(my_array, 6, json_object_new_int(7));
|
|
|
|
return my_array;
|
|
}
|
|
|
|
void test_array_del_idx(void);
|
|
void test_array_del_idx()
|
|
{
|
|
int rc;
|
|
size_t ii;
|
|
size_t orig_array_len;
|
|
json_object *my_array;
|
|
#ifdef TEST_FORMATTED
|
|
int sflags = 0;
|
|
#endif
|
|
|
|
my_array = make_array();
|
|
orig_array_len = json_object_array_length(my_array);
|
|
|
|
printf("my_array=\n");
|
|
for (ii = 0; ii < json_object_array_length(my_array); ii++)
|
|
{
|
|
json_object *obj = json_object_array_get_idx(my_array, ii);
|
|
printf("\t[%d]=%s\n", (int)ii, json_object_to_json_string(obj));
|
|
}
|
|
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
|
|
|
for (ii = 0; ii < orig_array_len; ii++)
|
|
{
|
|
rc = json_object_array_del_idx(my_array, 0, 1);
|
|
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n", rc,
|
|
json_object_to_json_string(my_array));
|
|
}
|
|
|
|
/* One more time, with the empty array: */
|
|
rc = json_object_array_del_idx(my_array, 0, 1);
|
|
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n", rc,
|
|
json_object_to_json_string(my_array));
|
|
|
|
json_object_put(my_array);
|
|
|
|
/* Delete all array indexes at once */
|
|
my_array = make_array();
|
|
rc = json_object_array_del_idx(my_array, 0, orig_array_len);
|
|
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)orig_array_len, rc,
|
|
json_object_to_json_string(my_array));
|
|
|
|
json_object_put(my_array);
|
|
|
|
/* Delete *more* than all array indexes at once */
|
|
my_array = make_array();
|
|
rc = json_object_array_del_idx(my_array, 0, orig_array_len + 1);
|
|
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)(orig_array_len + 1), rc,
|
|
json_object_to_json_string(my_array));
|
|
|
|
json_object_put(my_array);
|
|
|
|
/* Delete some array indexes, then add more */
|
|
my_array = make_array();
|
|
rc = json_object_array_del_idx(my_array, 0, orig_array_len - 1);
|
|
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)(orig_array_len - 1), rc,
|
|
json_object_to_json_string(my_array));
|
|
json_object_array_add(my_array, json_object_new_string("s1"));
|
|
json_object_array_add(my_array, json_object_new_string("s2"));
|
|
json_object_array_add(my_array, json_object_new_string("s3"));
|
|
|
|
printf("after adding more entries, my_array.to_string()=%s\n",
|
|
json_object_to_json_string(my_array));
|
|
json_object_put(my_array);
|
|
}
|
|
|
|
void test_array_list_expand_internal(void);
|
|
void test_array_list_expand_internal()
|
|
{
|
|
int rc;
|
|
size_t ii;
|
|
size_t idx;
|
|
json_object *my_array;
|
|
#ifdef TEST_FORMATTED
|
|
int sflags = 0;
|
|
#endif
|
|
|
|
my_array = make_array();
|
|
printf("my_array=\n");
|
|
for (ii = 0; ii < json_object_array_length(my_array); ii++)
|
|
{
|
|
json_object *obj = json_object_array_get_idx(my_array, ii);
|
|
printf("\t[%d]=%s\n", (int)ii, json_object_to_json_string(obj));
|
|
}
|
|
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
|
|
|
/* Put iNdex < array->size, no expand. */
|
|
rc = json_object_array_put_idx(my_array, 5, json_object_new_int(6));
|
|
printf("put_idx(5,6)=%d\n", rc);
|
|
|
|
/* array->size < Put Index < array->size * 2 <= SIZE_T_MAX, the size = array->size * 2. */
|
|
idx = ARRAY_LIST_DEFAULT_SIZE * 2 - 1;
|
|
rc = json_object_array_put_idx(my_array, idx, json_object_new_int(0));
|
|
printf("put_idx(%d,0)=%d\n", (int)(idx), rc);
|
|
|
|
/* array->size * 2 < Put Index, the size = Put Index. */
|
|
idx = ARRAY_LIST_DEFAULT_SIZE * 2 * 2 + 1;
|
|
rc = json_object_array_put_idx(my_array, idx, json_object_new_int(0));
|
|
printf("put_idx(%d,0)=%d\n", (int)(idx), rc);
|
|
|
|
/* SIZE_T_MAX <= Put Index, it will fail and the size will no change. */
|
|
idx = SIZE_MAX; // SIZE_MAX = SIZE_T_MAX
|
|
json_object *tmp = json_object_new_int(10);
|
|
rc = json_object_array_put_idx(my_array, idx, tmp);
|
|
printf("put_idx(SIZE_T_MAX,0)=%d\n", rc);
|
|
if (rc == -1)
|
|
{
|
|
json_object_put(tmp);
|
|
}
|
|
|
|
json_object_put(my_array);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
json_object *my_string, *my_int, *my_null, *my_object, *my_array;
|
|
size_t i;
|
|
#ifdef TEST_FORMATTED
|
|
int sflags = 0;
|
|
#endif
|
|
|
|
MC_SET_DEBUG(1);
|
|
|
|
#ifdef TEST_FORMATTED
|
|
sflags = parse_flags(argc, argv);
|
|
#endif
|
|
|
|
my_string = json_object_new_string("\t");
|
|
printf("my_string=%s\n", json_object_get_string(my_string));
|
|
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
|
json_object_put(my_string);
|
|
|
|
my_string = json_object_new_string("\\");
|
|
printf("my_string=%s\n", json_object_get_string(my_string));
|
|
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
|
json_object_put(my_string);
|
|
|
|
my_string = json_object_new_string("/");
|
|
printf("my_string=%s\n", json_object_get_string(my_string));
|
|
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
|
printf("my_string.to_string(NOSLASHESCAPE)=%s\n",
|
|
json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
|
|
json_object_put(my_string);
|
|
|
|
my_string = json_object_new_string("/foo/bar/baz");
|
|
printf("my_string=%s\n", json_object_get_string(my_string));
|
|
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
|
printf("my_string.to_string(NOSLASHESCAPE)=%s\n",
|
|
json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
|
|
json_object_put(my_string);
|
|
|
|
my_string = json_object_new_string("foo");
|
|
printf("my_string=%s\n", json_object_get_string(my_string));
|
|
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
|
|
|
|
my_int = json_object_new_int(9);
|
|
printf("my_int=%d\n", json_object_get_int(my_int));
|
|
printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int));
|
|
|
|
my_null = json_object_new_null();
|
|
printf("my_null.to_string()=%s\n", json_object_to_json_string(my_null));
|
|
|
|
my_array = json_object_new_array();
|
|
json_object_array_add(my_array, json_object_new_int(1));
|
|
json_object_array_add(my_array, json_object_new_int(2));
|
|
json_object_array_add(my_array, json_object_new_int(3));
|
|
json_object_array_put_idx(my_array, 4, json_object_new_int(5));
|
|
printf("my_array=\n");
|
|
for (i = 0; i < json_object_array_length(my_array); i++)
|
|
{
|
|
json_object *obj = json_object_array_get_idx(my_array, i);
|
|
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));
|
|
}
|
|
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
|
|
|
json_object_put(my_array);
|
|
|
|
test_array_del_idx();
|
|
test_array_list_expand_internal();
|
|
|
|
my_array = json_object_new_array_ext(5);
|
|
json_object_array_add(my_array, json_object_new_int(3));
|
|
json_object_array_add(my_array, json_object_new_int(1));
|
|
json_object_array_add(my_array, json_object_new_int(2));
|
|
json_object_array_put_idx(my_array, 4, json_object_new_int(0));
|
|
printf("my_array=\n");
|
|
for (i = 0; i < json_object_array_length(my_array); i++)
|
|
{
|
|
json_object *obj = json_object_array_get_idx(my_array, i);
|
|
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));
|
|
}
|
|
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
|
json_object_array_sort(my_array, sort_fn);
|
|
printf("my_array=\n");
|
|
for (i = 0; i < json_object_array_length(my_array); i++)
|
|
{
|
|
json_object *obj = json_object_array_get_idx(my_array, i);
|
|
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));
|
|
}
|
|
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
|
|
|
|
json_object *one = json_object_new_int(1);
|
|
json_object *result = json_object_array_bsearch(one, my_array, sort_fn);
|
|
printf("find json_object(1) in my_array successfully: %s\n",
|
|
json_object_to_json_string(result));
|
|
json_object_put(one);
|
|
|
|
my_object = json_object_new_object();
|
|
int rc = json_object_object_add(my_object, "abc", my_object);
|
|
if (rc != -1)
|
|
{
|
|
printf("ERROR: able to successfully add object to itself!\n");
|
|
fflush(stdout);
|
|
}
|
|
json_object_object_add(my_object, "abc", json_object_new_int(12));
|
|
json_object_object_add(my_object, "foo", json_object_new_string("bar"));
|
|
json_object_object_add(my_object, "bool0", json_object_new_boolean(0));
|
|
json_object_object_add(my_object, "bool1", json_object_new_boolean(1));
|
|
json_object_object_add(my_object, "baz", json_object_new_string("bang"));
|
|
|
|
json_object *baz_obj = json_object_new_string("fark");
|
|
json_object_get(baz_obj);
|
|
json_object_object_add(my_object, "baz", baz_obj);
|
|
json_object_object_del(my_object, "baz");
|
|
|
|
/* baz_obj should still be valid */
|
|
printf("baz_obj.to_string()=%s\n", json_object_to_json_string(baz_obj));
|
|
json_object_put(baz_obj);
|
|
|
|
/*json_object_object_add(my_object, "arr", my_array);*/
|
|
printf("my_object=\n");
|
|
json_object_object_foreach(my_object, key, val)
|
|
{
|
|
printf("\t%s: %s\n", key, json_object_to_json_string(val));
|
|
}
|
|
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);
|
|
json_object_put(my_object);
|
|
json_object_put(my_array);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|