From 45a4e774de3e2235b3e1bf9580177768464d3b90 Mon Sep 17 00:00:00 2001 From: Cengizhan Pasaoglu Date: Mon, 31 Jul 2023 13:14:50 +0300 Subject: [PATCH] Upgrade cJSON version to v1.7.16 (#2404) --- ATTRIBUTIONS.md | 2 +- test-tools/host-tool/external/cJSON/cJSON.c | 488 +++++++++++++------- test-tools/host-tool/external/cJSON/cJSON.h | 153 +++--- 3 files changed, 423 insertions(+), 220 deletions(-) diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md index 60b6bb1b7..ef788bf73 100644 --- a/ATTRIBUTIONS.md +++ b/ATTRIBUTIONS.md @@ -22,7 +22,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the | third party components | version number | latest release | vendor pages | CVE details | | --- | --- | --- | --- | --- | -| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | +| cjson | 1.7.16 | 1.7.16 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | | contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html | | freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html | | LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | | diff --git a/test-tools/host-tool/external/cJSON/cJSON.c b/test-tools/host-tool/external/cJSON/cJSON.c index 2e35351db..830d2a346 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.c +++ b/test-tools/host-tool/external/cJSON/cJSON.c @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ /* cJSON */ /* JSON parser in C. */ @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef ENABLE_LOCALES #include @@ -58,9 +59,33 @@ #include "cJSON.h" /* define our own boolean type */ +#ifdef true +#undef true +#endif #define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif #define false ((cJSON_bool)0) +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has + * been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0 / 0.0 +#endif +#endif + typedef struct { const unsigned char *json; size_t position; @@ -72,7 +97,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { if (!cJSON_IsString(item)) { return NULL; @@ -81,18 +106,27 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) return item->valuestring; } +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) +{ + if (!cJSON_IsNumber(item)) { + return (double)NAN; + } + + return item->valuedouble; +} + /* 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 != 10) + || (CJSON_VERSION_PATCH != 16) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif CJSON_PUBLIC(const char *) cJSON_Version(void) { static char version[15]; - snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR, - CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, + CJSON_VERSION_PATCH); return version; } @@ -127,8 +161,8 @@ typedef struct internal_hooks { } internal_hooks; #if defined(_MSC_VER) -/* work around MSVC error C2322: '...' address of dillimport '...' - is not static */ +/* work around MSVC error C2322: '...' address of dllimport '...' is not static + */ static void *CJSON_CDECL internal_malloc(size_t size) { @@ -150,13 +184,11 @@ internal_realloc(void *pointer, size_t size) #define internal_realloc realloc #endif -/* clang-format off */ -static internal_hooks global_hooks = { - internal_malloc, - internal_free, - internal_realloc -}; -/* clang-format on */ +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, + internal_realloc }; static unsigned char * cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) @@ -271,8 +303,8 @@ typedef struct { /* get a pointer to the buffer at the position */ #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) -/* Parse the input text to generate a number, and populate the result - into item. */ +/* Parse the input text to generate a number, and populate the result into item. + */ static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { @@ -287,9 +319,8 @@ parse_number(cJSON *const item, parse_buffer *const input_buffer) } /* copy the number into a temporary buffer and replace '.' with the decimal - * point of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking - * the end of the input */ + * point of the current locale (for strtod) This also takes care of '\0' not + * necessarily being available for marking the end of the input */ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) { @@ -363,6 +394,32 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) return object->valuedouble = number; } +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + /* 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)) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = + (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { + return NULL; + } + if (object->valuestring != NULL) { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + typedef struct { unsigned char *buffer; size_t length; @@ -438,9 +495,8 @@ ensure(printbuffer *const p, size_t needed) return NULL; } - if (newbuffer) { - memcpy(newbuffer, p->buffer, p->offset + 1); - } + + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } p->length = newsize; @@ -463,6 +519,14 @@ update_offset(printbuffer *const buffer) buffer->offset += strlen((const char *)buffer_pointer); } +/* securely comparison of floating-point variables */ +static cJSON_bool +compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + /* Render the number nicely from the given item into a string. */ static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) @@ -471,35 +535,37 @@ print_number(const cJSON *const item, printbuffer *const output_buffer) double d = item->valuedouble; int length = 0; size_t i = 0; - unsigned char - number_buffer[26]; /* temporary buffer to print the number into */ + unsigned char number_buffer[26] = { + 0 + }; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); - double test; + double test = 0.0; if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ - if ((d * 0) != 0) { - length = snprintf((char *)number_buffer, sizeof(number_buffer), "null"); + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } + 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 */ - length = - snprintf((char *)number_buffer, sizeof(number_buffer), "%1.15g", d); + length = sprintf((char *)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char *)number_buffer, "%lg", &test) != 1) - || ((double)test != d)) { + || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ - length = snprintf((char *)number_buffer, sizeof(number_buffer), - "%1.17g", d); + length = sprintf((char *)number_buffer, "%1.17g", d); } } - /* snprintf failed or buffer overrun occured */ + /* sprintf failed or buffer overrun occurred */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } @@ -709,8 +775,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { - goto fail; - /* string ended unexpectedly */ + goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ @@ -719,8 +784,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); if (output == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } } @@ -759,7 +823,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer) *output_pointer++ = input_pointer[1]; break; - /* UTF-16 literal */ + /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8( input_pointer, input_end, &output_pointer); @@ -805,7 +869,7 @@ print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { const unsigned char *input_pointer = NULL; - unsigned char *output = NULL, *output_end; + unsigned char *output = NULL; unsigned char *output_pointer = NULL; size_t output_length = 0; /* numbers of additional characters needed for escaping */ @@ -853,7 +917,6 @@ print_string_ptr(const unsigned char *const input, if (output == NULL) { return false; } - output_end = output + output_length + sizeof("\"\""); /* no characters have to be escaped */ if (escape_characters == 0) { @@ -902,9 +965,7 @@ print_string_ptr(const unsigned char *const input, break; default: /* escape and print as unicode codepoint */ - snprintf((char *)output_pointer, - output_end - output_pointer, "u%04x", - *input_pointer); + sprintf((char *)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -945,6 +1006,10 @@ buffer_skip_whitespace(parse_buffer *const buffer) return NULL; } + if (cannot_access_at_index(buffer, 0)) { + return buffer; + } + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { buffer->offset++; @@ -975,10 +1040,28 @@ skip_utf8_bom(parse_buffer *const buffer) return buffer; } -/* Parse an object - create a new root, and populate. */ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, + require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; @@ -987,12 +1070,12 @@ cJSON_ParseWithOpts(const char *value, const char **return_parse_end, global_error.json = NULL; global_error.position = 0; - if (value == NULL) { + if (value == NULL || 0 == buffer_length) { goto fail; } buffer.content = (const unsigned char *)value; - buffer.length = strlen((const char *)value) + sizeof(""); + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1056,7 +1139,13 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) return cJSON_ParseWithOpts(value, 0, 0); } -#define cjson_min(a, b) ((a < b) ? a : b) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) static unsigned char * print(const cJSON *const item, cJSON_bool format, @@ -1113,6 +1202,10 @@ fail: hooks->deallocate(buffer->buffer); } + if (printed != NULL) { + hooks->deallocate(printed); + } + return NULL; } @@ -1156,20 +1249,20 @@ cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) } CJSON_PUBLIC(cJSON_bool) -cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, - const cJSON_bool fmt) +cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, + const cJSON_bool format) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((len < 0) || (buf == NULL)) { + if ((length < 0) || (buffer == NULL)) { return false; } - p.buffer = (unsigned char *)buf; - p.length = (size_t)len; + p.buffer = (unsigned char *)buffer; + p.length = (size_t)length; p.offset = 0; p.noalloc = true; - p.format = fmt; + p.format = format; p.hooks = global_hooks; return print_value(item, &p); @@ -1341,8 +1434,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1361,8 +1453,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1370,13 +1461,16 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { - goto fail; - /* expected end of array */ + goto fail; /* expected end of array */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Array; item->child = head; @@ -1461,16 +1555,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { - goto fail; - /* not an object */ + goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { - goto success; - /* empty object */ + goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ @@ -1486,8 +1578,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); if (new_item == NULL) { - goto fail; - /* allocation failure */ + goto fail; /* allocation failure */ } /* attach next item to list */ @@ -1506,8 +1597,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_string(current_item, input_buffer)) { - goto fail; - /* faile to parse name */ + goto fail; /* failed to parse name */ } buffer_skip_whitespace(input_buffer); @@ -1517,16 +1607,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { - goto fail; - /* invalid object */ + goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); if (!parse_value(current_item, input_buffer)) { - goto fail; - /* failed to parse value */ + goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); } while (can_access_at_index(input_buffer, 0) @@ -1534,13 +1622,16 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer) if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { - goto fail; - /* expected end of object */ + goto fail; /* expected end of object */ } success: input_buffer->depth--; + if (head != NULL) { + head->prev = current_item; + } + item->type = cJSON_Object; item->child = head; @@ -1792,22 +1883,26 @@ add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; - if ((item == NULL) || (array == NULL)) { + if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; - + /* + * To find the last item in array quickly, we use prev in array + */ if (child == NULL) { /* list is empty, start new one */ array->child = item; + item->prev = item; + item->next = NULL; } else { /* append to the end */ - while (child->next) { - child = child->next; + if (child->prev) { + suffix_object(child->prev, item); + array->child->prev = item; } - suffix_object(child, item); } return true; @@ -1847,7 +1942,8 @@ add_item_to_object(cJSON *const object, const char *const string, char *new_key = NULL; int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL)) { + if ((object == NULL) || (string == NULL) || (item == NULL) + || (object == item)) { return false; } @@ -2028,7 +2124,7 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) return NULL; } - if (item->prev != NULL) { + if (item != parent->child) { /* not the first element */ item->prev->next = item->next; } @@ -2041,6 +2137,11 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) /* first element */ parent->child = item->next; } + else if (item->next == NULL) { + /* last element */ + parent->child->prev = item->prev; + } + /* make sure the detached item doesn't point anywhere anymore */ item->prev = NULL; item->next = NULL; @@ -2121,7 +2222,8 @@ 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; } @@ -2135,12 +2237,24 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, if (replacement->next != NULL) { replacement->next->prev = replacement; } - if (replacement->prev != NULL) { - replacement->prev->next = replacement; - } if (parent->child == item) { + if (parent->child->prev == parent->child) { + replacement->prev = replacement; + } parent->child = replacement; } + else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was + * the parent's child + */ + if (replacement->prev != NULL) { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) { + parent->child->prev = replacement; + } + } item->next = NULL; item->prev = NULL; @@ -2149,15 +2263,15 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { if (which < 0) { - return; + return false; } - cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), - newitem); + return cJSON_ReplaceItemViaPointer( + array, get_array_item(array, (size_t)which), newitem); } static cJSON_bool @@ -2175,25 +2289,27 @@ replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, } replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { + return false; + } + replacement->type &= ~cJSON_StringIsConst; - cJSON_ReplaceItemViaPointer( + return cJSON_ReplaceItemViaPointer( object, get_object_item(object, string, case_sensitive), replacement); - - return true; } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, false); + return replace_item_in_object(object, string, newitem, false); } -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) { - replace_item_in_object(object, string, newitem, true); + return replace_item_in_object(object, string, newitem, true); } /* Create basic types: */ @@ -2227,11 +2343,11 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { cJSON *item = cJSON_New_Item(&global_hooks); if (item) { - item->type = b ? cJSON_True : cJSON_False; + item->type = boolean ? cJSON_True : cJSON_False; } return item; @@ -2357,6 +2473,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) } a = cJSON_CreateArray(); + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if (!n) { @@ -2372,6 +2489,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2403,6 +2524,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2434,10 +2559,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count) { size_t i = 0; cJSON *n = NULL; @@ -2465,6 +2595,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) p = n; } + if (a && a->child) { + a->child->prev = n; + } + return a; } @@ -2532,6 +2666,9 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) } child = child->next; } + if (newitem && newitem->child) { + newitem->child->prev = newchild; + } return newitem; @@ -2543,55 +2680,93 @@ fail: return NULL; } +static void +skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void +skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { + *input += static_strlen("*/"); + return; + } + } +} + +static void +minify_string(char **input, char **output) +{ + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } + else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + CJSON_PUBLIC(void) cJSON_Minify(char *json) { - unsigned char *into = (unsigned char *)json; + char *into = json; if (json == NULL) { return; } - while (*json) { - if (*json == ' ') { - json++; - } - else if (*json == '\t') { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') { - json++; - } - else if (*json == '\n') { - json++; - } - else if ((*json == '/') && (json[1] == '/')) { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) { + while (json[0] != '\0') { + switch (json[0]) { + case ' ': + case '\t': + case '\r': + case '\n': json++; - } - } - else if ((*json == '/') && (json[1] == '*')) { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) { - json++; - } - json += 2; - } - else if (*json == '\"') { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) { - if (*json == '\\') { - *into++ = (unsigned char)*json++; + break; + + case '/': + if (json[1] == '/') { + skip_oneline_comment(&json); } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else { - /* All other characters. */ - *into++ = (unsigned char)*json++; + else if (json[1] == '*') { + skip_multiline_comment(&json); + } + else { + json++; + } + break; + + case '\"': + minify_string(&json, (char **)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; } } @@ -2692,8 +2867,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) - || cJSON_IsInvalid(a)) { + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } @@ -2726,7 +2900,7 @@ cJSON_Compare(const cJSON *const a, const cJSON *const b, return true; case cJSON_Number: - if (a->valuedouble == b->valuedouble) { + if (compare_double(a->valuedouble, b->valuedouble)) { return true; } return false; diff --git a/test-tools/host-tool/external/cJSON/cJSON.h b/test-tools/host-tool/external/cJSON/cJSON.h index d437196a3..2cafdcf59 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.h +++ b/test-tools/host-tool/external/cJSON/cJSON.h @@ -1,24 +1,24 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - */ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ #ifndef cJSON__h #define cJSON__h @@ -35,30 +35,34 @@ extern "C" { #ifdef __WINDOWS__ -/** - * When compiling for windows, we specify a specific calling convention to avoid - * issues where we are being called from a project with a different default - * calling convention. For windows you have 3 define options: - * CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever - * dllexport symbols - * CJSON_EXPORT_SYMBOLS - Define this on library build when you want to - * dllexport symbols (default) - * CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - * - * For *nix builds that support visibility attribute, you can define similar - * behavior by setting default visibility to hidden by adding - * -fvisibility=hidden (for gcc) - * or - * -xldscope=hidden (for sun cc) - * to CFLAGS, then using the CJSON_API_VISIBILITY flag to "export" the same - * symbols the way CJSON_EXPORT_SYMBOLS does - */ +/* When compiling for windows, we specify a specific calling convention to avoid +issues where we are being called from a project with a different default calling +convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever +dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you +want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you +want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar +behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way +CJSON_EXPORT_SYMBOLS does + +*/ #define CJSON_CDECL __cdecl #define CJSON_STDCALL __stdcall /* export symbols by default, this is necessary for copy pasting the C and - header file */ + * header file */ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \ && !defined(CJSON_EXPORT_SYMBOLS) #define CJSON_EXPORT_SYMBOLS @@ -86,7 +90,7 @@ extern "C" { /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 10 +#define CJSON_VERSION_PATCH 16 #include @@ -107,11 +111,11 @@ extern "C" { /* The cJSON structure: */ typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use - GetArraySize/GetArrayItem/GetObjectItem */ + * GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; /* An array or object item will have a child pointer pointing to a chain of - the items in the array/object. */ + * the items in the array/object. */ struct cJSON *child; /* The type of the item, as above. */ @@ -125,7 +129,7 @@ typedef struct cJSON { double valuedouble; /* The item's name string, if this item is the child of, or is in the list - of subitems of an object. */ + * of subitems of an object. */ char *string; } cJSON; @@ -140,7 +144,7 @@ typedef struct cJSON_Hooks { typedef int cJSON_bool; /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse - them. This is to prevent stack overflows. */ + * them. This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif @@ -159,6 +163,8 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLength(const char *value, size_t buffer_length); /* ParseWithOpts allows you to require (and check) that the JSON is null * terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then @@ -167,6 +173,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, + const char **return_parse_end, + cJSON_bool require_null_terminated); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); @@ -185,7 +195,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); /* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); /* Returns the number of items in an array (or object). */ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); @@ -205,8 +215,9 @@ cJSON_HasObjectItem(const cJSON *object, const char *string); * when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); -/* Check if the item is a string and return its valuestring */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); @@ -233,18 +244,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so - it will not be freed by cJSON_Delete */ + * it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); -/* Create an object/arrray that only references it's elements so - they will not be freed by cJSON_Delete */ +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); -/* These utilities create an Array of count items. */ +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the + * number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); +CJSON_PUBLIC(cJSON *) +cJSON_CreateStringArray(const char *const *strings, int count); /* Append item to the specified array/object. */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); @@ -264,7 +278,7 @@ cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); -/* Remove/Detatch items from Arrays/Objects. */ +/* Remove/Detach items from Arrays/Objects. */ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); @@ -286,32 +300,35 @@ cJSON_InsertItemInArray( CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); -CJSON_PUBLIC(void) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new - memory that will need to be released. With recurse!=0, it will duplicate any - children connected to the item. The item->next and ->prev pointers are always - zero on return from Duplicate. */ + * memory that will need to be released. With recurse!=0, it will duplicate any + * children connected to the item. The item->next and ->prev pointers are always + * zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or - * invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or - * case insensitive (0) */ + * invalid, they will be considered unequal. case_sensitive determines if object + * keys are treated case sensitive (1) or case insensitive (0) */ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from + * strings. The input pointer json cannot point to a read-only address area, + * such as a string constant, but should point to a readable and writable + * address area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. - They return the added item or NULL on failure. */ + * They return the added item or NULL on failure. */ CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); CJSON_PUBLIC(cJSON *) @@ -336,7 +353,7 @@ CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); /* When assigning an integer value, it needs to be propagated to valuedouble - too. */ + * too. */ #define cJSON_SetIntValue(object, number) \ ((object) ? (object)->valueint = (object)->valuedouble = (number) \ : (number)) @@ -345,6 +362,18 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); #define cJSON_SetNumberValue(object, number) \ ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \ : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type + * of object is cJSON_String */ +CJSON_PUBLIC(char *) +cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns + * cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) \ + | ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ #define cJSON_ArrayForEach(element, array) \ @@ -352,7 +381,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); element = element->next) /* malloc/free objects using the malloc/free functions that have been set with - cJSON_InitHooks */ + * cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void) cJSON_free(void *object);