diff --git a/fuzzing/cjson_extended_fuzzer.cpp b/fuzzing/cjson_extended_fuzzer.cpp new file mode 100644 index 00000000..64053ed3 --- /dev/null +++ b/fuzzing/cjson_extended_fuzzer.cpp @@ -0,0 +1,164 @@ +#include +#include + +extern "C" { + #include "../cJSON.c" +} + +int intArray[10]; +float floatArray[10]; +double doubleArray[10]; +const char *stringArray[10]; + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + + std::string json_string = fdp.ConsumeRandomLengthString(); + cJSON *json = cJSON_ParseWithOpts(json_string.c_str(), NULL, fdp.ConsumeBool()); + + if (json != NULL) { + + cJSON *new_json = cJSON_Duplicate(json, fdp.ConsumeBool()); + if (new_json != NULL) { + cJSON_Delete(new_json); + } + + // Modifify the object + int opsToPerform = fdp.ConsumeIntegralInRange(5, 20); + for (int i = 0; i < opsToPerform; i++) { + int op = fdp.ConsumeIntegralInRange(0, 13); + switch (op) { + case 0: + cJSON_AddBoolToObject(json, fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeBool()); + break; + case 1: + cJSON_AddTrueToObject(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 2: + cJSON_AddNumberToObject(json, fdp.ConsumeRandomLengthString().c_str(), 1.0); + break; + case 3: + cJSON_GetObjectItem(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 4: + cJSON_GetObjectItemCaseSensitive(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 5: + cJSON_AddNullToObject(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 6: + cJSON_AddStringToObject(json, fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeRandomLengthString().c_str()); + break; + case 7: + cJSON_AddRawToObject(json, fdp.ConsumeRandomLengthString().c_str(), fdp.ConsumeRandomLengthString().c_str()); + break; + case 8: + cJSON_AddArrayToObject(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 9: + cJSON_AddFalseToObject(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 10: + cJSON_AddObjectToObject(json, fdp.ConsumeRandomLengthString().c_str()); + break; + case 11: + cJSON_SetNumberHelper(json, fdp.ConsumeFloatingPoint()); + break; + case 12: + cJSON_SetValuestring(json, fdp.ConsumeRandomLengthString().c_str()); + break; + default: + break; + } + } + + // Array creation routines. + for (int i = 0; i < 10; i++) { + intArray[i] = fdp.ConsumeIntegral(); + floatArray[i] = fdp.ConsumeFloatingPoint(); + doubleArray[i] = fdp.ConsumeFloatingPoint(); + stringArray[i] = json_string.c_str(); + } + cJSON *cJsonIntArray = cJSON_CreateIntArray(intArray, 10); + if (cJsonIntArray != NULL) { + cJSON_Delete(cJsonIntArray); + } + cJSON *floatIntArray = cJSON_CreateFloatArray(floatArray, 10); + if (floatIntArray != NULL) { + cJSON_Delete(floatIntArray); + } + cJSON *cJsonDoubleArray = cJSON_CreateDoubleArray(doubleArray, 10); + if (cJsonDoubleArray != NULL) { + cJSON_Delete(cJsonDoubleArray); + } + cJSON *cJsonStringArray = cJSON_CreateStringArray(stringArray, 10); + if (cJsonStringArray != NULL) { + cJSON_Delete(cJsonStringArray); + } + + // Replace + cJSON *nullObj = cJSON_CreateNull(); + if (nullObj != NULL) { + if (cJSON_ReplaceItemInObject(json, fdp.ConsumeRandomLengthString().c_str(), nullObj) == false) { + cJSON_Delete(nullObj); + } + } + // Print the object + unsigned char printed_unformatted[1024]; + unsigned char printed_formatted[1024]; + printbuffer unformatted_buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + /* buffer for formatted printing */ + unformatted_buffer.buffer = printed_unformatted; + unformatted_buffer.length = sizeof(printed_unformatted); + unformatted_buffer.offset = 0; + unformatted_buffer.noalloc = true; + unformatted_buffer.hooks = global_hooks; + print_object(json, &unformatted_buffer); + + // Type checks + opsToPerform = fdp.ConsumeIntegralInRange(5, 20); + for (int i = 0; i < opsToPerform; i++) { + int op = fdp.ConsumeIntegralInRange(0, 9); + switch (op) { + case 0: + if (cJSON_IsArray(json)) { + cJSON_GetArraySize(json); + cJSON_GetArrayItem(json, 10); + } + break; + case 1: + cJSON_IsObject(json); + break; + case 2: + cJSON_IsString(json); + break; + case 3: + cJSON_IsRaw(json); + break; + case 4: + cJSON_IsNull(json); + break; + case 5: + cJSON_IsBool(json); + break; + case 6: + cJSON_IsTrue(json); + break; + case 7: + cJSON_IsFalse(json); + break; + case 8: + cJSON_IsInvalid(json); + break; + default: + break; + } + } + } + + cJSON_Delete(json); + return 0; +} diff --git a/fuzzing/cjson_read_compare.cpp b/fuzzing/cjson_read_compare.cpp new file mode 100644 index 00000000..1983f4de --- /dev/null +++ b/fuzzing/cjson_read_compare.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +extern "C" { +#include "../cJSON.h" +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + cJSON *a_json, *b_json; + FuzzedDataProvider fdp(data, size); + + std::string payload1 = fdp.ConsumeRandomLengthString(); + std::string payload2 = fdp.ConsumeRandomLengthString(); + + a_json = cJSON_ParseWithOpts(payload1.c_str(), NULL, 1); + b_json = cJSON_ParseWithOpts(payload2.c_str(), NULL, 1); + + if(a_json != NULL && b_json != NULL) { + cJSON_Compare(a_json, b_json, fdp.ConsumeBool()); + } + + if (a_json != NULL) { + cJSON_Delete(a_json); + } + if (b_json != NULL) { + cJSON_Delete(b_json); + } + + return 0; +} diff --git a/fuzzing/ossfuzz.sh b/fuzzing/ossfuzz.sh index a2da64bf..bcd4aecc 100755 --- a/fuzzing/ossfuzz.sh +++ b/fuzzing/ossfuzz.sh @@ -12,6 +12,14 @@ $CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \ -o $OUT/cjson_read_fuzzer \ $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a +$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_compare.cpp -I. \ + -o $OUT/cjson_read_compare \ + $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a + +$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_extended_fuzzer.cpp -I. \ + -o $OUT/cjson_extended_fuzzer \ + $LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a + find $SRC/cjson/fuzzing/inputs -name "*" | \ xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip