From 05dac23b1137a35c5a606492941bf295e30c5a73 Mon Sep 17 00:00:00 2001 From: Ensiform Date: Wed, 4 Sep 2024 11:13:26 -0500 Subject: [PATCH] Update cJSON to 2024-08-29 commit Includes fixes through 1.7.18 Also replaced isnan/isinf checks with isfinite if isfinite is available, as isnan/isinf is not compatible when compiling with fast math. --- code/cJSON/cJSON.c | 78 ++++++++++++++++++++++++++++++++++++---------- code/cJSON/cJSON.h | 2 +- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/code/cJSON/cJSON.c b/code/cJSON/cJSON.c index c78aac6..40d0eb7 100644 --- a/code/cJSON/cJSON.c +++ b/code/cJSON/cJSON.c @@ -96,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) return (const char*) (global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) { - if (!cJSON_IsString(item)) + if (!cJSON_IsString(item)) { return NULL; } @@ -106,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) return item->valuestring; } -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) { - if (!cJSON_IsNumber(item)) + if (!cJSON_IsNumber(item)) { return (double) NAN; } @@ -117,7 +117,7 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) } /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif @@ -263,10 +263,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; } if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { global_hooks.deallocate(item->string); + item->string = NULL; } global_hooks.deallocate(item); item = next; @@ -397,16 +399,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) return object->valuedouble = number; } +/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ 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->type & cJSON_String) || (object->type & cJSON_IsReference)) + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { return NULL; } - if (strlen(valuestring) <= strlen(object->valuestring)) + /* return NULL if the object is corrupted or valuestring is NULL */ + if (object->valuestring == NULL || valuestring == NULL) { + return NULL; + } + + 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; } @@ -511,7 +530,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) return NULL; } - + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } @@ -558,14 +577,18 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } /* This checks for NaN and Infinity */ +#ifdef isfinite + if (!isfinite(d)) +#else if (isnan(d) || isinf(d)) +#endif { length = sprintf((char*)number_buffer, "null"); } - else if(d == (double)item->valueint) - { - length = sprintf((char*)number_buffer, "%d", item->valueint); - } + else if(d == (double)item->valueint) + { + length = sprintf((char*)number_buffer, "%d", item->valueint); + } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ @@ -888,6 +911,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu if (output != NULL) { input_buffer->hooks.deallocate(output); + output = NULL; } if (input_pointer != NULL) @@ -1107,7 +1131,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer } buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1230,6 +1254,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i /* free the buffer */ hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; } return printed; @@ -1238,11 +1263,13 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; } if (printed != NULL) { hooks->deallocate(printed); + printed = NULL; } return NULL; @@ -1283,6 +1310,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON if (!print_value(item, &p)) { global_hooks.deallocate(p.buffer); + p.buffer = NULL; return NULL; } @@ -1654,6 +1682,11 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu current_item = new_item; } + if (cannot_access_at_index(input_buffer, 1)) + { + goto fail; /* nothing comes after the comma */ + } + /* parse the name of the child */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); @@ -2186,7 +2219,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; } @@ -2264,7 +2297,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON { cJSON *after_inserted = NULL; - if (which < 0) + if (which < 0 || newitem == NULL) { return false; } @@ -2275,6 +2308,11 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON return add_item_to_array(array, newitem); } + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + newitem->next = after_inserted; newitem->prev = after_inserted->prev; after_inserted->prev = newitem; @@ -2291,7 +2329,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) { return false; } @@ -2361,6 +2399,11 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO cJSON_free(replacement->string); } replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if (replacement->string == NULL) + { + return false; + } + replacement->type &= ~cJSON_StringIsConst; return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); @@ -2693,7 +2736,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co if (a && a->child) { a->child->prev = n; } - + return a; } @@ -3111,4 +3154,5 @@ CJSON_PUBLIC(void *) cJSON_malloc(size_t size) CJSON_PUBLIC(void) cJSON_free(void *object) { global_hooks.deallocate(object); + object = NULL; } diff --git a/code/cJSON/cJSON.h b/code/cJSON/cJSON.h index 95a9cf6..88cf0bc 100644 --- a/code/cJSON/cJSON.h +++ b/code/cJSON/cJSON.h @@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 15 +#define CJSON_VERSION_PATCH 18 #include