Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.15)

project(cJSON
VERSION 1.7.19
Expand Down
10 changes: 9 additions & 1 deletion cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL;
}

if (p->offset > ((size_t)-1) - 1 - needed)
{
return NULL;
}

needed += p->offset + 1;
if (needed <= p->length)
{
Expand Down Expand Up @@ -662,7 +667,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
return true;
}

/* parse 4 digit hexadecimal number */
/* parse 4 digit hexadecimal number
* returns 0 for both the valid sequence 0000 and for any invalid hex digit.
* Callers disambiguate by pointer position. */
static unsigned parse_hex4(const unsigned char * const input)
{
unsigned int h = 0;
Expand Down Expand Up @@ -2414,6 +2421,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
return true;
}

/* Note: Returns false if out-of-range, which is indistinguishable from NULL-arg / allocation failures */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0)
Expand Down
41 changes: 38 additions & 3 deletions cJSON_Utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,19 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++)
{
unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target);

/* found the target? */
if (target_pointer != NULL)
{
if (cJSON_IsArray(object))
{
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/"));
if (full_pointer == NULL)
{
cJSON_free(target_pointer);
return NULL;
}
/* check if conversion to unsigned long is valid
* This should be eliminated at compile time by dead code elimination
* if size_t is an alias of unsigned long, or if it is bigger */
Expand All @@ -240,6 +246,11 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
if (cJSON_IsObject(object))
{
unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2);
if (full_pointer == NULL)
{
cJSON_free(target_pointer);
return NULL;
}
full_pointer[0] = '/';
encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string);
strcat((char*)full_pointer, (char*)target_pointer);
Expand Down Expand Up @@ -275,6 +286,10 @@ static cJSON_bool decode_array_index_from_pointer(const unsigned char * const po
{
size_t parsed_index = 0;
size_t position = 0;
if ((pointer[0] == '\0') || (pointer[0] == '/'))
{
return 0;
}

if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/')))
{
Expand Down Expand Up @@ -915,6 +930,15 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_

if (opcode == MOVE)
{
const char *f = from->valuestring;
const char *p = path->valuestring;
size_t flen = strlen(f);
if ((strncmp(p, f, flen) == 0) && ((p[flen] == '/') || (p[flen] == '\0')))
{
/* missing "from" for copy/move. */
status = 14;
goto cleanup;
}
value = detach_path(object, (unsigned char*)from->valuestring, case_sensitive);
}
if (opcode == COPY)
Expand Down Expand Up @@ -1119,6 +1143,11 @@ static void compose_patch(cJSON * const patches, const unsigned char * const ope
size_t path_length = strlen((const char*)path);
unsigned char *full_path = (unsigned char*)cJSON_malloc(path_length + suffix_length + sizeof("/"));

if (full_path == NULL)
{
return;
}

sprintf((char*)full_path, "%s/", (const char*)path);
encode_string_as_pointer(full_path + path_length + 1, suffix);

Expand Down Expand Up @@ -1173,7 +1202,10 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
cJSON *from_child = from->child;
cJSON *to_child = to->child;
unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */

if (new_path == NULL)
{
return;
}
/* generate patches for all array elements that exist in both "from" and "to" */
for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++)
{
Expand Down Expand Up @@ -1244,7 +1276,10 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
size_t path_length = strlen((const char*)path);
size_t from_child_name_length = pointer_encoded_length((unsigned char*)from_child->string);
unsigned char *new_path = (unsigned char*)cJSON_malloc(path_length + from_child_name_length + sizeof("/"));

if (new_path == NULL)
{
return;
}
sprintf((char*)new_path, "%s/", path);
encode_string_as_pointer(new_path + path_length + 1, (unsigned char*)from_child->string);

Expand Down Expand Up @@ -1420,7 +1455,7 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
{
if (to_child != NULL)
{
diff = strcmp(from_child->string, to_child->string);
diff = compare_strings((unsigned char*)from_child->string, (unsigned char*)to_child->string, case_sensitive);
}
else
{
Expand Down