From 9a970b9ff66fae45f45ea4bf9bce602aa9b8d0c7 Mon Sep 17 00:00:00 2001 From: myd7349 Date: Sun, 14 Apr 2019 19:41:28 +0800 Subject: [PATCH 01/35] CMake: Improve install target --- CMakeLists.txt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 033a882..6e2b2e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,13 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in" install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig") -install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_LIB}") +install(TARGETS "${CJSON_LIB}" + EXPORT "${CJSON_LIB}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" +) if (BUILD_SHARED_AND_STATIC_LIBS) install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") endif() @@ -186,7 +192,13 @@ if(ENABLE_CJSON_UTILS) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY) - install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}") + install(TARGETS "${CJSON_UTILS_LIB}" + EXPORT "${CJSON_UTILS_LIB}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" + INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}" + ) if (BUILD_SHARED_AND_STATIC_LIBS) install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") endif() From 3a4cfa84c3ce5f7a6439a689dcacbdd42732ed0e Mon Sep 17 00:00:00 2001 From: Simon Sobisch Date: Mon, 6 May 2019 21:07:06 +0200 Subject: [PATCH 02/35] allow to override PIC_FLAGS and compiler std --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 93fffcc..7368179 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,8 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) INSTALL ?= cp -a +CC = gcc -std=c89 + # validate gcc version for use fstack-protector-strong MIN_GCC_VERSION = "4.9" GCC_VERSION := "`$(CC) -dumpversion`" @@ -34,7 +36,8 @@ else CFLAGS += -fstack-protector endif -R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS) +PIC_FLAGS = -fPIC +R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS) uname := $(shell sh -c 'uname -s 2>/dev/null || echo false') From 5fe80a94b64f542f100634c4caea843b254ed3e1 Mon Sep 17 00:00:00 2001 From: Alan_scut Date: Wed, 22 May 2019 10:24:13 +0800 Subject: [PATCH 03/35] add comment for cJSON_Minify function --- cJSON.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cJSON.h b/cJSON.h index 592986b..71a6d2e 100644 --- a/cJSON.h +++ b/cJSON.h @@ -250,7 +250,9 @@ The item->next and ->prev pointers are always zero on return from Duplicate. */ * 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 adress area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. From 16f56300e48716dfb2e5af978f38992c55257c6d Mon Sep 17 00:00:00 2001 From: singku Date: Wed, 29 May 2019 21:25:33 +0000 Subject: [PATCH 04/35] Replace strcpy with strncpy, sprintf with snprintf --- cJSON.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/cJSON.c b/cJSON.c index 60b72c0..5f30d6a 100644 --- a/cJSON.c +++ b/cJSON.c @@ -95,7 +95,7 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { CJSON_PUBLIC(const char*) cJSON_Version(void) { static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); return version; } @@ -499,22 +499,22 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out /* This checks for NaN and Infinity */ if ((d * 0) != 0) { - length = sprintf((char*)number_buffer, "null"); + length = snprintf((char*)number_buffer, sizeof(number_buffer), "null"); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); + length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d)) { /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); + length = snprintf((char*)number_buffer, sizeof(number_buffer), "%1.17g", d); } } - /* sprintf failed or buffer overrun occurred */ + /* snprintf failed or buffer overrun occurred */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; @@ -848,15 +848,16 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe return false; } + const char quotes[] = "\"\""; /* empty string */ if (input == NULL) { - output = ensure(output_buffer, sizeof("\"\"")); + output = ensure(output_buffer, sizeof(quotes)); if (output == NULL) { return false; } - strcpy((char*)output, "\"\""); + strncpy((char*)output, quotes, output_buffer->length - output_buffer->offset); return true; } @@ -887,7 +888,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe } output_length = (size_t)(input_pointer - input) + escape_characters; - output = ensure(output_buffer, output_length + sizeof("\"\"")); + output = ensure(output_buffer, output_length + sizeof(quotes)); if (output == NULL) { return false; @@ -943,7 +944,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe break; default: /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); + snprintf((char*)output_pointer, output_buffer->length - (output_pointer - output_buffer->buffer), "u%04x", *input_pointer); output_pointer += 4; break; } @@ -1286,32 +1287,38 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp switch ((item->type) & 0xFF) { case cJSON_NULL: - output = ensure(output_buffer, 5); + { + const char buff[] = "null"; + output = ensure(output_buffer, sizeof(buff)); if (output == NULL) { return false; } - strcpy((char*)output, "null"); + strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); return true; - + } case cJSON_False: - output = ensure(output_buffer, 6); + { + const char buff[] = "false"; + output = ensure(output_buffer, sizeof(buff)); if (output == NULL) { return false; } - strcpy((char*)output, "false"); + strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); return true; - + } case cJSON_True: - output = ensure(output_buffer, 5); + { + const char buff[] = "true"; + output = ensure(output_buffer, sizeof(buff)); if (output == NULL) { return false; } - strcpy((char*)output, "true"); + strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); return true; - + } case cJSON_Number: return print_number(item, output_buffer); From 110f184d18c3a33debc45bcf066e32fb61021baf Mon Sep 17 00:00:00 2001 From: Sanjeev BA Date: Sun, 16 Jun 2019 07:58:03 +0900 Subject: [PATCH 05/35] Fix typos. Signed-off-by: Sanjeev BA --- cJSON.c | 2 +- cJSON.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cJSON.c b/cJSON.c index 60b72c0..85e8ba6 100644 --- a/cJSON.c +++ b/cJSON.c @@ -132,7 +132,7 @@ 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) { return malloc(size); diff --git a/cJSON.h b/cJSON.h index 592986b..7399259 100644 --- a/cJSON.h +++ b/cJSON.h @@ -203,7 +203,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so * 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 +/* 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); @@ -225,7 +225,7 @@ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJ CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(void) 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); CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); From 85ceadb4b42bd8c80893595bf25a4a8acb24dae4 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Tue, 25 Jun 2019 17:25:23 +0800 Subject: [PATCH 06/35] Add a comment to the parameter count of the cJSON_CreateIntArray function. --- cJSON.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cJSON.h b/cJSON.h index 592986b..a2ae97f 100644 --- a/cJSON.h +++ b/cJSON.h @@ -208,7 +208,8 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); 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); From 9d766f07a793e3277ff14c231540887179001651 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Fri, 28 Jun 2019 14:22:02 +0800 Subject: [PATCH 07/35] fix const cast warnings in cJSON_GetStringValue --- cJSON.c | 2 +- cJSON.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cJSON.c b/cJSON.c index 60b72c0..87f815b 100644 --- a/cJSON.c +++ b/cJSON.c @@ -79,7 +79,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; } diff --git a/cJSON.h b/cJSON.h index 592986b..09bc74c 100644 --- a/cJSON.h +++ b/cJSON.h @@ -174,7 +174,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st 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); +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); From f7f175fdf298b644efdd43e38be66608c13ccdb6 Mon Sep 17 00:00:00 2001 From: Randy Date: Thu, 11 Jul 2019 13:56:07 +0200 Subject: [PATCH 08/35] add fuzz target --- fuzzing/cjson_read_fuzzer.cc | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 fuzzing/cjson_read_fuzzer.cc diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.cc new file mode 100644 index 0000000..d7af5c2 --- /dev/null +++ b/fuzzing/cjson_read_fuzzer.cc @@ -0,0 +1,41 @@ +#include +#include + +#include "../cJSON.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if((data[0] == '\0') || (size < 3) || (data[1] == '\0')) return 0; + + cJSON *json = cJSON_Parse((const char*)data + 2); + + if(json == NULL) return 0; + + int do_format = 0; + char *printed_json = NULL; + + if(data[1] == 'f') do_format = 1; + + if(data[0] == 'b') + { + /* buffered printing */ + printed_json = cJSON_PrintBuffered(json, 1, do_format); + } + else + { + /* unbuffered printing */ + if(do_format) + { + printed_json = cJSON_Print(json); + } + else + { + printed_json = cJSON_PrintUnformatted(json); + } + } + + if(printed_json != NULL) free(printed_json); + cJSON_Delete(json); + + return 0; +} From 2691e142f4a881b470e7d5e889ef4ca4a589cadf Mon Sep 17 00:00:00 2001 From: Randy Date: Thu, 11 Jul 2019 14:42:27 +0200 Subject: [PATCH 09/35] update fuzzer --- fuzzing/cjson_read_fuzzer.cc | 38 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.cc index d7af5c2..be2fe67 100644 --- a/fuzzing/cjson_read_fuzzer.cc +++ b/fuzzing/cjson_read_fuzzer.cc @@ -1,30 +1,38 @@ #include #include +#include #include "../cJSON.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if((data[0] == '\0') || (size < 3) || (data[1] == '\0')) return 0; + size_t offset = 4; - cJSON *json = cJSON_Parse((const char*)data + 2); + if(size < offset) return 0; + if(data[0] != '1' && data[0] != '0') return 0; + if(data[1] != '1' && data[1] != '0') return 0; + if(data[2] != '1' && data[2] != '0') return 0; + if(data[3] != '1' && data[3] != '0') return 0; + + int minify = data[0] == '1' ? 1 : 0; + int require_termination = data[1] == '1' ? 1 : 0; + int formatted = data[2] == '1' ? 1 : 0; + int buffered = data[3] == '1' ? 1 : 0; + + cJSON *json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination); if(json == NULL) return 0; - int do_format = 0; char *printed_json = NULL; - if(data[1] == 'f') do_format = 1; - - if(data[0] == 'b') + if(buffered) { - /* buffered printing */ - printed_json = cJSON_PrintBuffered(json, 1, do_format); + printed_json = cJSON_PrintBuffered(json, 1, formatted); } else { /* unbuffered printing */ - if(do_format) + if(formatted) { printed_json = cJSON_Print(json); } @@ -35,6 +43,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) } if(printed_json != NULL) free(printed_json); + + if(minify) + { + unsigned char *copied = (unsigned char*)malloc(size); + + memcpy(copied, data + offset, size); + + cJSON_Minify((char*)printed_json); + free(copied); + } + + cJSON_Delete(json); return 0; From e6bc5d16e6e1c336523fbda6493c4f7ee3863415 Mon Sep 17 00:00:00 2001 From: Randy Date: Thu, 11 Jul 2019 15:03:04 +0200 Subject: [PATCH 10/35] update fuzzer --- fuzzing/cjson_read_fuzzer.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.cc index be2fe67..57cbd0c 100644 --- a/fuzzing/cjson_read_fuzzer.cc +++ b/fuzzing/cjson_read_fuzzer.cc @@ -19,9 +19,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) int formatted = data[2] == '1' ? 1 : 0; int buffered = data[3] == '1' ? 1 : 0; - cJSON *json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination); + unsigned char *copied = (unsigned char*)malloc(size); + if(copied == NULL) return 0; - if(json == NULL) return 0; + memcpy(copied, data, size); + copied[size-1] = '\0'; + + cJSON *json = cJSON_ParseWithOpts((const char*)copied + offset, NULL, require_termination); + + if(json == NULL) + { + free(copied); + return 0; + } char *printed_json = NULL; @@ -46,16 +56,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if(minify) { - unsigned char *copied = (unsigned char*)malloc(size); - - memcpy(copied, data + offset, size); - - cJSON_Minify((char*)printed_json); - free(copied); + cJSON_Minify((char*)copied + offset); } - cJSON_Delete(json); + free(copied); return 0; } From 2d6db59c7bddee0f052b5ed511bcfd4306badaa9 Mon Sep 17 00:00:00 2001 From: Randy Date: Thu, 11 Jul 2019 15:09:10 +0200 Subject: [PATCH 11/35] update fuzzer --- fuzzing/cjson_read_fuzzer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.cc index 57cbd0c..3b76894 100644 --- a/fuzzing/cjson_read_fuzzer.cc +++ b/fuzzing/cjson_read_fuzzer.cc @@ -8,7 +8,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size_t offset = 4; - if(size < offset) return 0; + if(size <= offset) return 0; if(data[0] != '1' && data[0] != '0') return 0; if(data[1] != '1' && data[1] != '0') return 0; if(data[2] != '1' && data[2] != '0') return 0; From c680faea56d4089d857c091f39679384fe6f392e Mon Sep 17 00:00:00 2001 From: Vemake Date: Wed, 24 Jul 2019 20:46:41 +0800 Subject: [PATCH 12/35] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cf1f09a..3cfd6f8 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ $(UTILS_SHARED_VERSION): $(UTILS_OBJ) #cJSON $(CJSON_OBJ): cJSON.c cJSON.h #cJSON_Utils -$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h +$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h #links .so -> .so.1 -> .so.1.0.0 From 166c814cda8e78bcf27fbbc815f945ceb21af5c5 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Mon, 12 Aug 2019 17:06:29 +0800 Subject: [PATCH 13/35] eliminate warning when compiling cJSON --- tests/unity/src/unity.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unity/src/unity.c b/tests/unity/src/unity.c index 0f2d2de..d02610a 100644 --- a/tests/unity/src/unity.c +++ b/tests/unity/src/unity.c @@ -268,14 +268,14 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) UNITY_DOUBLE number = input_number; /* print minus sign (including for negative zero) */ - if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f)) + if (number < (double)0.0f || (number == (double)0.0f && (double)1.0f / number < (double)0.0f)) { UNITY_OUTPUT_CHAR('-'); number = -number; } /* handle zero, NaN, and +/- infinity */ - if (number == 0.0f) UnityPrint("0"); + if (number == (double)0.0f) UnityPrint("0"); else if (isnan(number)) UnityPrint("nan"); else if (isinf(number)) UnityPrint("inf"); else @@ -286,10 +286,10 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) char buf[16]; /* scale up or down by powers of 10 */ - while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; } - while (number < 100000.0f) { number *= 10.0f; exponent--; } - while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; } - while (number > 1000000.0f) { number /= 10.0f; exponent++; } + while (number < (double)(100000.0f / 1e6f)) { number *= (double)1e6f; exponent -= 6; } + while (number < (double)100000.0f) { number *= (double)10.0f; exponent--; } + while (number > (double)(1000000.0f * 1e6f)) { number /= (double)1e6f; exponent += 6; } + while (number > (double)1000000.0f) { number /= (double)10.0f; exponent++; } /* round to nearest integer */ n = ((UNITY_INT32)(number + number) + 1) / 2; From b6da0d6565f7b5095fd5ecb9aa197393324788e0 Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Sat, 24 Aug 2019 22:43:33 +0900 Subject: [PATCH 14/35] Correct typo error --- cJSON.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cJSON.h b/cJSON.h index 592986b..c00ea4e 100644 --- a/cJSON.h +++ b/cJSON.h @@ -160,7 +160,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ 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); From bd1a375028a29f2ee39a96ac8459b8ea4711ed0a Mon Sep 17 00:00:00 2001 From: Randy Date: Sat, 24 Aug 2019 17:42:48 +0200 Subject: [PATCH 15/35] add fuzzer driver, integrate with build system --- fuzzing/CMakeLists.txt | 5 ++++ fuzzing/cjson_read_fuzzer.cc | 24 ++++++++++------ fuzzing/fuzz_main.c | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 fuzzing/fuzz_main.c diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index fdd7126..84278e8 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -26,3 +26,8 @@ if (ENABLE_FUZZING) endif() + +if(ENABLE_CJSON_TEST) + ADD_EXECUTABLE(fuzz_main fuzz_main.c) + TARGET_LINK_LIBRARIES(fuzz_main cjson) +endif() \ No newline at end of file diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.cc index 3b76894..4ec4322 100644 --- a/fuzzing/cjson_read_fuzzer.cc +++ b/fuzzing/cjson_read_fuzzer.cc @@ -4,9 +4,17 @@ #include "../cJSON.h" -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +#ifdef __cplusplus +extern "C" +#endif +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + cJSON *json; size_t offset = 4; + unsigned char *copied; + char *printed_json = NULL; + int minify, require_termination, formatted, buffered; + if(size <= offset) return 0; if(data[0] != '1' && data[0] != '0') return 0; @@ -14,18 +22,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if(data[2] != '1' && data[2] != '0') return 0; if(data[3] != '1' && data[3] != '0') return 0; - int minify = data[0] == '1' ? 1 : 0; - int require_termination = data[1] == '1' ? 1 : 0; - int formatted = data[2] == '1' ? 1 : 0; - int buffered = data[3] == '1' ? 1 : 0; + minify = data[0] == '1' ? 1 : 0; + require_termination = data[1] == '1' ? 1 : 0; + formatted = data[2] == '1' ? 1 : 0; + buffered = data[3] == '1' ? 1 : 0; - unsigned char *copied = (unsigned char*)malloc(size); + copied = (unsigned char*)malloc(size); if(copied == NULL) return 0; memcpy(copied, data, size); copied[size-1] = '\0'; - cJSON *json = cJSON_ParseWithOpts((const char*)copied + offset, NULL, require_termination); + json = cJSON_ParseWithOpts((const char*)copied + offset, NULL, require_termination); if(json == NULL) { @@ -33,8 +41,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) return 0; } - char *printed_json = NULL; - if(buffered) { printed_json = cJSON_PrintBuffered(json, 1, formatted); diff --git a/fuzzing/fuzz_main.c b/fuzzing/fuzz_main.c new file mode 100644 index 0000000..e004115 --- /dev/null +++ b/fuzzing/fuzz_main.c @@ -0,0 +1,56 @@ +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C90 */ + +#include "cjson_read_fuzzer.cc" + +/* fuzz target entry point, works without libFuzzer */ + +int main(int argc, char **argv) +{ + FILE *f; + char *buf = NULL; + long siz_buf; + + if(argc < 2) + { + fprintf(stderr, "no input file\n"); + goto err; + } + + f = fopen(argv[1], "rb"); + if(f == NULL) + { + fprintf(stderr, "error opening input file %s\n", argv[1]); + goto err; + } + + fseek(f, 0, SEEK_END); + + siz_buf = ftell(f); + rewind(f); + + if(siz_buf < 1) goto err; + + buf = (char*)malloc((size_t)siz_buf); + if(buf == NULL) + { + fprintf(stderr, "malloc() failed\n"); + goto err; + } + + if(fread(buf, (size_t)siz_buf, 1, f) != 1) + { + fprintf(stderr, "fread() failed\n"); + goto err; + } + + (void)LLVMFuzzerTestOneInput((uint8_t*)buf, (size_t)siz_buf); + +err: + free(buf); + + return 0; +} From c61573f1af9df53515cbdc5dae39a9b2e8a7740f Mon Sep 17 00:00:00 2001 From: Alanscut Date: Wed, 11 Sep 2019 09:51:30 +0800 Subject: [PATCH 16/35] format adjustment --- cJSON.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cJSON.h b/cJSON.h index a2ae97f..1e8567a 100644 --- a/cJSON.h +++ b/cJSON.h @@ -208,8 +208,8 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); -/* 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.*/ +/* 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); From 189b51c5dae85e193ec1601079e4a2a61145f3b4 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Wed, 11 Sep 2019 10:42:44 +0800 Subject: [PATCH 17/35] format comment --- cJSON.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cJSON.h b/cJSON.h index f19692b..42c1cc6 100644 --- a/cJSON.h +++ b/cJSON.h @@ -245,14 +245,14 @@ CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const ch /* 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. */ + * 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) */ 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, +/* 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 adress area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); From ae49da2b61a378b9c0e07572ca759cd305c8b9c8 Mon Sep 17 00:00:00 2001 From: Alanscut <948467222@qq.com> Date: Sat, 21 Sep 2019 17:42:25 +0800 Subject: [PATCH 18/35] Revert "Replace strcpy with strncpy, sprintf with snprintf" --- cJSON.c | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/cJSON.c b/cJSON.c index f04010f..85e8ba6 100644 --- a/cJSON.c +++ b/cJSON.c @@ -95,7 +95,7 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { 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; } @@ -499,22 +499,22 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out /* This checks for NaN and Infinity */ if ((d * 0) != 0) { - length = snprintf((char*)number_buffer, sizeof(number_buffer), "null"); + length = sprintf((char*)number_buffer, "null"); } 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)) { /* 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 occurred */ + /* sprintf failed or buffer overrun occurred */ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; @@ -848,16 +848,15 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe return false; } - const char quotes[] = "\"\""; /* empty string */ if (input == NULL) { - output = ensure(output_buffer, sizeof(quotes)); + output = ensure(output_buffer, sizeof("\"\"")); if (output == NULL) { return false; } - strncpy((char*)output, quotes, output_buffer->length - output_buffer->offset); + strcpy((char*)output, "\"\""); return true; } @@ -888,7 +887,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe } output_length = (size_t)(input_pointer - input) + escape_characters; - output = ensure(output_buffer, output_length + sizeof(quotes)); + output = ensure(output_buffer, output_length + sizeof("\"\"")); if (output == NULL) { return false; @@ -944,7 +943,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe break; default: /* escape and print as unicode codepoint */ - snprintf((char*)output_pointer, output_buffer->length - (output_pointer - output_buffer->buffer), "u%04x", *input_pointer); + sprintf((char*)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -1287,38 +1286,32 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp switch ((item->type) & 0xFF) { case cJSON_NULL: - { - const char buff[] = "null"; - output = ensure(output_buffer, sizeof(buff)); + output = ensure(output_buffer, 5); if (output == NULL) { return false; } - strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); + strcpy((char*)output, "null"); return true; - } + case cJSON_False: - { - const char buff[] = "false"; - output = ensure(output_buffer, sizeof(buff)); + output = ensure(output_buffer, 6); if (output == NULL) { return false; } - strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); + strcpy((char*)output, "false"); return true; - } + case cJSON_True: - { - const char buff[] = "true"; - output = ensure(output_buffer, sizeof(buff)); + output = ensure(output_buffer, 5); if (output == NULL) { return false; } - strncpy((char*)output, buff, output_buffer->length - output_buffer->offset); + strcpy((char*)output, "true"); return true; - } + case cJSON_Number: return print_number(item, output_buffer); From e52b212dbfc583f933ee199bd54e82fdfa8da561 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Sun, 29 Sep 2019 18:53:21 +0800 Subject: [PATCH 19/35] fix typos in REAM.md file --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3b39c85..06b0de9 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ Note that you have to delete them at some point, otherwise you will get a memory You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`. To add items to an array, use `cJSON_AddItemToArray` to append items to the end. -Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere. +Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere. To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right. If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak. @@ -221,7 +221,7 @@ Because an array is stored as a linked list, iterating it via index is inefficie You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`. To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`. -Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere. +Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere. If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak. @@ -326,7 +326,7 @@ char* create_monitor(void) goto end; } /* after creation was successful, immediately add it to the monitor, - * thereby transfering ownership of the pointer to it */ + * thereby transferring ownership of the pointer to it */ cJSON_AddItemToObject(monitor, "name", name); resolutions = cJSON_CreateArray(); From dc56e24f7f1d3ffc72e8b5a0039c6137b43e89d4 Mon Sep 17 00:00:00 2001 From: randy408 Date: Mon, 14 Oct 2019 17:12:13 +0200 Subject: [PATCH 20/35] add build script --- fuzzing/ossfuzz.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 fuzzing/ossfuzz.sh diff --git a/fuzzing/ossfuzz.sh b/fuzzing/ossfuzz.sh new file mode 100644 index 0000000..8de60e4 --- /dev/null +++ b/fuzzing/ossfuzz.sh @@ -0,0 +1,19 @@ +#!/bin/bash -eu + +# This script is meant to be run by +# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Dockerfile + +mkdir build +cd build +cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF .. +make -j$(nproc) + +$CXX $CXXFLAGS -std=c++11 -I. \ + $SRC/cjson/fuzzing/cjson_read_fuzzer.cc \ + -o $OUT/cjson_read_fuzzer \ + $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a + +find $SRC/cjson/fuzzing/inputs -name "*" | \ + xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip + +cp $SRC/cjson/fuzzing/json.dict $OUT/cjson_read_fuzzer.dict From 26772a8ef7affe5ed96c831eddfb6b69146cc2d2 Mon Sep 17 00:00:00 2001 From: Bernt Johan Damslora Date: Thu, 17 Oct 2019 14:03:15 +0200 Subject: [PATCH 21/35] Add const qualifier to cJSON_CreateStringArray Adds a const qualifier to the strings in the array to avoid discarding it from arguments. --- cJSON.c | 2 +- cJSON.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cJSON.c b/cJSON.c index 85e8ba6..96b65f1 100644 --- a/cJSON.c +++ b/cJSON.c @@ -2524,7 +2524,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) 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; diff --git a/cJSON.h b/cJSON.h index 42c1cc6..0ecd179 100644 --- a/cJSON.h +++ b/cJSON.h @@ -213,7 +213,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); 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(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); From bcc91ecbc37c68390f3c9339cb51428c30dd2b1e Mon Sep 17 00:00:00 2001 From: Julian Ste <31321934+julian-st@users.noreply.github.com> Date: Sat, 19 Oct 2019 13:53:21 +0200 Subject: [PATCH 22/35] initilize variables in print_number --- cJSON.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cJSON.c b/cJSON.c index 85e8ba6..9dfaa24 100644 --- a/cJSON.c +++ b/cJSON.c @@ -487,9 +487,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out 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) { From ec8d2f9c2e9de7524f9ddd78d39605d5fc6987ef Mon Sep 17 00:00:00 2001 From: randy408 Date: Mon, 21 Oct 2019 15:27:47 +0200 Subject: [PATCH 23/35] convert fuzz target to c89, optimize --- fuzzing/CMakeLists.txt | 2 +- ...son_read_fuzzer.cc => cjson_read_fuzzer.c} | 28 ++++++++----------- fuzzing/fuzz_main.c | 4 +-- fuzzing/ossfuzz.sh | 4 +-- 4 files changed, 16 insertions(+), 22 deletions(-) rename fuzzing/{cjson_read_fuzzer.cc => cjson_read_fuzzer.c} (77%) diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 84278e8..587368d 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -28,6 +28,6 @@ if (ENABLE_FUZZING) endif() if(ENABLE_CJSON_TEST) - ADD_EXECUTABLE(fuzz_main fuzz_main.c) + ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c) TARGET_LINK_LIBRARIES(fuzz_main cjson) endif() \ No newline at end of file diff --git a/fuzzing/cjson_read_fuzzer.cc b/fuzzing/cjson_read_fuzzer.c similarity index 77% rename from fuzzing/cjson_read_fuzzer.cc rename to fuzzing/cjson_read_fuzzer.c index 4ec4322..b2692ed 100644 --- a/fuzzing/cjson_read_fuzzer.cc +++ b/fuzzing/cjson_read_fuzzer.c @@ -4,9 +4,8 @@ #include "../cJSON.h" -#ifdef __cplusplus -extern "C" -#endif +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */ + int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { cJSON *json; @@ -17,6 +16,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if(size <= offset) return 0; + if(data[size-1] != '\0') return 0; if(data[0] != '1' && data[0] != '0') return 0; if(data[1] != '1' && data[1] != '0') return 0; if(data[2] != '1' && data[2] != '0') return 0; @@ -27,19 +27,9 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) formatted = data[2] == '1' ? 1 : 0; buffered = data[3] == '1' ? 1 : 0; - copied = (unsigned char*)malloc(size); - if(copied == NULL) return 0; + json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination); - memcpy(copied, data, size); - copied[size-1] = '\0'; - - json = cJSON_ParseWithOpts((const char*)copied + offset, NULL, require_termination); - - if(json == NULL) - { - free(copied); - return 0; - } + if(json == NULL) return 0; if(buffered) { @@ -62,11 +52,17 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if(minify) { + copied = (unsigned char*)malloc(size); + if(copied == NULL) return 0; + + memcpy(copied, data, size); + cJSON_Minify((char*)copied + offset); + + free(copied); } cJSON_Delete(json); - free(copied); return 0; } diff --git a/fuzzing/fuzz_main.c b/fuzzing/fuzz_main.c index e004115..09dc156 100644 --- a/fuzzing/fuzz_main.c +++ b/fuzzing/fuzz_main.c @@ -2,9 +2,7 @@ #include #include -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C90 */ - -#include "cjson_read_fuzzer.cc" +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */ /* fuzz target entry point, works without libFuzzer */ diff --git a/fuzzing/ossfuzz.sh b/fuzzing/ossfuzz.sh index 8de60e4..fe4bf16 100644 --- a/fuzzing/ossfuzz.sh +++ b/fuzzing/ossfuzz.sh @@ -8,8 +8,8 @@ cd build cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF .. make -j$(nproc) -$CXX $CXXFLAGS -std=c++11 -I. \ - $SRC/cjson/fuzzing/cjson_read_fuzzer.cc \ +$CC $CFLAGS -std=c89 -I. \ + $SRC/cjson/fuzzing/cjson_read_fuzzer.c \ -o $OUT/cjson_read_fuzzer \ $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a From 6b728982f2073ea334ad436ebb5dae92486e0812 Mon Sep 17 00:00:00 2001 From: Randy Date: Tue, 22 Oct 2019 12:45:13 +0200 Subject: [PATCH 24/35] ossfuzz.sh: fix permission bits --- fuzzing/ossfuzz.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 fuzzing/ossfuzz.sh diff --git a/fuzzing/ossfuzz.sh b/fuzzing/ossfuzz.sh old mode 100644 new mode 100755 From 73b0e739d0cfc7036ef36c2736970032605eb6c7 Mon Sep 17 00:00:00 2001 From: Randy Date: Tue, 22 Oct 2019 13:32:41 +0200 Subject: [PATCH 25/35] fuzz: add support for compiling with c++ compiler --- fuzzing/cjson_read_fuzzer.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fuzzing/cjson_read_fuzzer.c b/fuzzing/cjson_read_fuzzer.c index b2692ed..e9f733d 100644 --- a/fuzzing/cjson_read_fuzzer.c +++ b/fuzzing/cjson_read_fuzzer.c @@ -2,6 +2,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #include "../cJSON.h" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */ @@ -66,3 +70,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) return 0; } + +#ifdef __cplusplus +} +#endif \ No newline at end of file From 49a0ede475c9042a868f15718fad911f7423597a Mon Sep 17 00:00:00 2001 From: Randy Date: Tue, 22 Oct 2019 13:37:41 +0200 Subject: [PATCH 26/35] ossfuzz: build with c++ compiler --- fuzzing/ossfuzz.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fuzzing/ossfuzz.sh b/fuzzing/ossfuzz.sh index fe4bf16..a2da64b 100755 --- a/fuzzing/ossfuzz.sh +++ b/fuzzing/ossfuzz.sh @@ -8,8 +8,7 @@ cd build cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF .. make -j$(nproc) -$CC $CFLAGS -std=c89 -I. \ - $SRC/cjson/fuzzing/cjson_read_fuzzer.c \ +$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \ -o $OUT/cjson_read_fuzzer \ $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a From a417b183c6661a41f78a4ff039ad8a01321cdcf5 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Tue, 29 Oct 2019 12:47:36 +0800 Subject: [PATCH 27/35] add new line to endif --- fuzzing/CMakeLists.txt | 3 ++- fuzzing/cjson_read_fuzzer.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 587368d..1166000 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -30,4 +30,5 @@ endif() if(ENABLE_CJSON_TEST) ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c) TARGET_LINK_LIBRARIES(fuzz_main cjson) -endif() \ No newline at end of file +endif() + diff --git a/fuzzing/cjson_read_fuzzer.c b/fuzzing/cjson_read_fuzzer.c index e9f733d..aa9c7ba 100644 --- a/fuzzing/cjson_read_fuzzer.c +++ b/fuzzing/cjson_read_fuzzer.c @@ -73,4 +73,5 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) #ifdef __cplusplus } -#endif \ No newline at end of file +#endif + From de99175cd0892828dcd0838a78fdf5c6ccde2866 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Tue, 29 Oct 2019 14:21:16 +0800 Subject: [PATCH 28/35] fix rmdir error (#401) * fix rmdir error --- Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8209959..3994b50 100644 --- a/Makefile +++ b/Makefile @@ -141,9 +141,8 @@ uninstall-cjson: uninstall-utils $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED) $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION) $(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO) - rmdir $(INSTALL_LIBRARY_PATH) $(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h - rmdir $(INSTALL_INCLUDE_PATH) + #cJSON_Utils uninstall-utils: $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED) @@ -151,7 +150,11 @@ uninstall-utils: $(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO) $(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h -uninstall: uninstall-utils uninstall-cjson +remove-dir: + $(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH)) + $(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH)) + +uninstall: uninstall-utils uninstall-cjson remove-dir clean: $(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files From bb059dc2e1dbcc47c6e2a932f762c390c8aaf45e Mon Sep 17 00:00:00 2001 From: Alanscut Date: Tue, 29 Oct 2019 15:48:11 +0800 Subject: [PATCH 29/35] add uninstall target in cmake --- CMakeLists.txt | 3 +++ library_config/uninstall.cmake | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 library_config/uninstall.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f977963..34ad39f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,6 +253,9 @@ if(ENABLE_CJSON_TEST) DEPENDS ${TEST_CJSON}) endif() +#Create the uninstall target +add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake") + # Enable the use of locales option(ENABLE_LOCALES "Enable the use of locales" ON) if(ENABLE_LOCALES) diff --git a/library_config/uninstall.cmake b/library_config/uninstall.cmake new file mode 100644 index 0000000..e751ec4 --- /dev/null +++ b/library_config/uninstall.cmake @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.8.5) + +set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") + +if(NOT EXISTS ${MANIFEST}) + message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}") +endif() + +file(STRINGS ${MANIFEST} files) +foreach(file ${files}) + if(EXISTS ${file} OR IS_SYMLINK ${file}) + message(STATUS "Removing: ${file}") + + execute_process(COMMAND rm -f ${file} + RESULT_VARIABLE result + OUTPUT_QUIET + ERROR_VARIABLE stderr + ERROR_STRIP_TRAILING_WHITESPACE + ) + + if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "${stderr}") + endif() + else() + message(STATUS "Does-not-exist: ${file}") + endif() +endforeach(file) From 44547317756f1d3b5d6ee05b49c6b1d577b31fda Mon Sep 17 00:00:00 2001 From: Alanscut Date: Tue, 29 Oct 2019 16:14:22 +0800 Subject: [PATCH 30/35] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 06b0de9..7c6ffaf 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ Run this command in the directory with the source code and it will automatically make all ``` -If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. +If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`. ### Including cJSON If you installed it via CMake or the Makefile, you can include cJSON like this: From 4755aea8377fd69202db235d4f4a49440c8a2270 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Fri, 1 Nov 2019 11:30:14 +0800 Subject: [PATCH 31/35] fix make failed in mac os --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3994b50..0e58d5c 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ $(CJSON_SHARED_VERSION): $(CJSON_OBJ) $(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS) #cJSON_Utils $(UTILS_SHARED_VERSION): $(UTILS_OBJ) - $(CC) -shared -o $@ $< $(UTILS_SO_LDFLAG) $(LDFLAGS) + $(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS) #objects #cJSON From c64854b26edb9760fd5fb6fcbc5b6d7aa3b61236 Mon Sep 17 00:00:00 2001 From: rolegic <8974088+rolegic@users.noreply.github.com> Date: Fri, 15 Nov 2019 15:43:43 +0100 Subject: [PATCH 32/35] Fixed different argument between declaration and definition --- cJSON.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cJSON.c b/cJSON.c index 8a77508..eeb5c51 100644 --- a/cJSON.c +++ b/cJSON.c @@ -1199,20 +1199,20 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON return (char*)p.buffer; } -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) +CJSON_PUBLIC(cJSON_bool) 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); @@ -2290,12 +2290,12 @@ 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; From 446ff0d6cc58de3380ce39f506cb858ca2d2947f Mon Sep 17 00:00:00 2001 From: Alanscut Date: Wed, 27 Nov 2019 11:08:35 +0800 Subject: [PATCH 33/35] fix issue#327 --- tests/print_number.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/print_number.c b/tests/print_number.c index f2385f3..3fbf9cb 100644 --- a/tests/print_number.c +++ b/tests/print_number.c @@ -27,6 +27,8 @@ static void assert_print_number(const char *expected, double input) { unsigned char printed[1024]; + unsigned char new_buffer[26]; + unsigned int i = 0; cJSON item[1]; printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; buffer.buffer = printed; @@ -34,11 +36,29 @@ static void assert_print_number(const char *expected, double input) buffer.offset = 0; buffer.noalloc = true; buffer.hooks = global_hooks; + buffer.buffer = new_buffer; memset(item, 0, sizeof(item)); + memset(new_buffer, 0, sizeof(new_buffer)); cJSON_SetNumberValue(item, input); - TEST_ASSERT_TRUE_MESSAGE(print_number(item, &buffer), "Failed to print number."); + + /* In MinGW or visual studio(before 2015),the exponten is represented using three digits,like:"1e-009","1e+017" + * remove extra "0" to output "1e-09" or "1e+17",which makes testcase PASS */ + for(i = 0;i 3 && new_buffer[i] =='0') + { + if((new_buffer[i-3] =='e' && new_buffer[i-2] == '-' && new_buffer[i] =='0') ||(new_buffer[i-2] =='e' && new_buffer[i-1] =='+')) + { + while(new_buffer[i] !='\0') + { + new_buffer[i] = new_buffer[i+1]; + i++; + } + } + } + } TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, buffer.buffer, "Printed number is not as expected."); } From f3b6ad15f0282e8f6ed31e7169d893bb8630ff68 Mon Sep 17 00:00:00 2001 From: Erez Oxman Date: Thu, 28 Nov 2019 14:15:44 +0200 Subject: [PATCH 34/35] Added blank lines in Readme.md Added blank lines before list items and headings. This change creates consistency between different markdown parsers. There's no difference in the output of Github flavored markdown. See https://babelmark.github.io/ --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 7c6ffaf..c50b135 100644 --- a/README.md +++ b/README.md @@ -80,11 +80,13 @@ philosophy as JSON itself. Simple, dumb, out of the way. There are several ways to incorporate cJSON into your project. #### copying the source + Because the entire library is only one C file and one header file, you can just copy `cJSON.h` and `cJSON.c` to your projects source and start using it. cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible. #### CMake + With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it. ``` @@ -102,6 +104,7 @@ make And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library. You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`: + * `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default) * `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default) * `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default) @@ -127,6 +130,7 @@ make DESTDIR=$pkgdir install On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows. #### Makefile + **NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs. If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON: @@ -140,6 +144,7 @@ make all If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`. ### Including cJSON + If you installed it via CMake or the Makefile, you can include cJSON like this: ```c @@ -171,6 +176,7 @@ An item of this type represents a JSON value. The type is stored in `type` as a To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type. The type can be one of the following: + * `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes. * `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`. * `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`. @@ -182,6 +188,7 @@ The type can be one of the following: * `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON. Additionally there are the following two flags: + * `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not it's children/valuestring. * `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`. @@ -193,6 +200,7 @@ Note that you have to delete them at some point, otherwise you will get a memory **Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well. #### Basic types + * **null** is created with `cJSON_CreateNull` * **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool` * **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint` @@ -272,6 +280,7 @@ If you have a rough idea of how big your resulting string will be, you can use ` These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough. ### Example + In this example we want to build and parse the following JSON: ```json @@ -295,7 +304,9 @@ In this example we want to build and parse the following JSON: ``` #### Printing + Let's build the above JSON and print it to a string: + ```c //create a monitor with a list of supported resolutions //NOTE: Returns a heap allocated string, you are required to free it after use. @@ -373,6 +384,7 @@ end: ``` Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier: + ```c //NOTE: Returns a heap allocated string, you are required to free it after use. char *create_monitor_with_helpers(void) @@ -428,6 +440,7 @@ end: ``` #### Parsing + In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output: ```c @@ -514,6 +527,7 @@ cJSON doesn't support arrays and objects that are nested too deeply because this In general cJSON is **not thread safe**. However it is thread safe under the following conditions: + * `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead) * `cJSON_InitHooks` is only ever called before using cJSON in any threads. * `setlocale` is never called before all calls to cJSON functions have returned. From 500a9db81bca54027ce8de2ce42b48fa89782e78 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Thu, 5 Dec 2019 11:05:07 +0800 Subject: [PATCH 35/35] fix memory leak mentioned in issue 414 --- cJSON_Utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 7df4db2..b890d17 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -216,6 +216,7 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje if (child_index > ULONG_MAX) { cJSON_free(target_pointer); + cJSON_free(full_pointer); return NULL; } sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* / */