Skip to content

Commit

Permalink
Merge branch 'DaveGamble:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Hironobu-Ishii authored Sep 26, 2024
2 parents fbc4adc + 12c4bf1 commit 08a9dc0
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
27 changes: 24 additions & 3 deletions cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
char *copy = NULL;
size_t v1_len;
size_t v2_len;
/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
{
Expand All @@ -413,8 +415,17 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
return NULL;
}
if (strlen(valuestring) <= strlen(object->valuestring))

v1_len = strlen(valuestring);
v2_len = strlen(object->valuestring);

if (v1_len <= v2_len)
{
/* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
{
return NULL;
}
strcpy(object->valuestring, valuestring);
return object->valuestring;
}
Expand Down Expand Up @@ -2220,7 +2231,7 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c

CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
{
if ((parent == NULL) || (item == NULL))
if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
{
return NULL;
}
Expand Down Expand Up @@ -2742,7 +2753,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co
}

/* Duplication */
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);

CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
{
return cJSON_Duplicate_rec(item, 0, recurse );
}

cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
{
cJSON *newitem = NULL;
cJSON *child = NULL;
Expand Down Expand Up @@ -2789,7 +2807,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
child = item->child;
while (child != NULL)
{
newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
if(depth >= CJSON_CIRCULAR_LIMIT) {
goto fail;
}
newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild)
{
goto fail;
Expand Down
6 changes: 6 additions & 0 deletions cJSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ typedef int cJSON_bool;
#define CJSON_NESTING_LIMIT 1000
#endif

/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif

/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);

Expand Down
53 changes: 53 additions & 0 deletions tests/misc_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,23 @@ static void cjson_should_not_parse_to_deeply_nested_jsons(void)
TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(deep_json), "To deep JSONs should not be parsed.");
}

static void cjson_should_not_follow_too_deep_circular_references(void)
{
cJSON *o = cJSON_CreateArray();
cJSON *a = cJSON_CreateArray();
cJSON *b = cJSON_CreateArray();
cJSON *x;

cJSON_AddItemToArray(o, a);
cJSON_AddItemToArray(a, b);
cJSON_AddItemToArray(b, o);

x = cJSON_Duplicate(o, 1);
TEST_ASSERT_NULL(x);
cJSON_DetachItemFromArray(b, 0);
cJSON_Delete(o);
}

static void cjson_set_number_value_should_set_numbers(void)
{
cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
Expand Down Expand Up @@ -280,6 +297,21 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
}

static void cjson_detach_item_via_pointer_should_return_null_if_item_prev_is_null(void)
{
cJSON list[2];
cJSON parent[1];

memset(list, '\0', sizeof(list));

/* link the list */
list[0].next = &(list[1]);

parent->child = &list[0];
TEST_ASSERT_NULL_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])), "Failed to detach in the middle.");
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach in the middle.");
}

static void cjson_replace_item_via_pointer_should_replace_items(void)
{
cJSON replacements[3];
Expand Down Expand Up @@ -456,6 +488,24 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
cJSON_Delete(item);
}

static void cjson_set_valuestring_should_return_null_if_strings_overlap(void)
{
cJSON *obj;
char* str;
char* str2;

obj = cJSON_Parse("\"foo0z\"");

str = cJSON_SetValuestring(obj, "abcde");
str += 1;
/* The string passed to strcpy overlap which is not allowed.*/
str2 = cJSON_SetValuestring(obj, str);
/* If it overlaps, the string will be messed up.*/
TEST_ASSERT_TRUE(strcmp(str, "bcde") == 0);
TEST_ASSERT_NULL(str2);
cJSON_Delete(obj);
}

static void *CJSON_CDECL failing_realloc(void *pointer, size_t size)
{
(void)size;
Expand Down Expand Up @@ -744,11 +794,14 @@ int CJSON_CDECL main(void)
RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
RUN_TEST(typecheck_functions_should_check_type);
RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
RUN_TEST(cjson_should_not_follow_too_deep_circular_references);
RUN_TEST(cjson_set_number_value_should_set_numbers);
RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
RUN_TEST(cjson_detach_item_via_pointer_should_return_null_if_item_prev_is_null);
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
RUN_TEST(cjson_set_valuestring_should_return_null_if_strings_overlap);
RUN_TEST(ensure_should_fail_on_failed_realloc);
RUN_TEST(skip_utf8_bom_should_skip_bom);
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
Expand Down

0 comments on commit 08a9dc0

Please sign in to comment.