From 839fbe0d63b58ecfd5b82578a02a24f03e5c359c Mon Sep 17 00:00:00 2001 From: Simon Resch Date: Fri, 8 Nov 2024 22:20:40 -0500 Subject: [PATCH] Add fuzz tests for json_object/point/array apis Extends the coverage of fuzz tests executed in OSS-Fuzz. --- fuzz/json_array_fuzzer.cc | 27 ++++++++++++++++ fuzz/json_array_fuzzer.dict | 21 ++++++++++++ fuzz/json_object_fuzzer.cc | 44 +++++++++++++++++++++++++ fuzz/json_object_fuzzer.dict | 21 ++++++++++++ fuzz/json_pointer_fuzzer.cc | 53 +++++++++++++++++++++++++++++++ fuzz/json_pointer_fuzzer.dict | 21 ++++++++++++ fuzz/tokener_parse_ex_fuzzer.dict | 3 ++ 7 files changed, 190 insertions(+) create mode 100644 fuzz/json_array_fuzzer.cc create mode 100644 fuzz/json_array_fuzzer.dict create mode 100644 fuzz/json_object_fuzzer.cc create mode 100644 fuzz/json_object_fuzzer.dict create mode 100644 fuzz/json_pointer_fuzzer.cc create mode 100644 fuzz/json_pointer_fuzzer.dict diff --git a/fuzz/json_array_fuzzer.cc b/fuzz/json_array_fuzzer.cc new file mode 100644 index 00000000..999cd828 --- /dev/null +++ b/fuzz/json_array_fuzzer.cc @@ -0,0 +1,27 @@ +#include + +#include "json.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + json_object *my_array = json_object_new_array(); + for (int i = 0; i < 3; ++i) { + json_object *jso = json_tokener_parse(fdp.ConsumeRandomLengthString(10).c_str()); + if (jso == NULL) { + continue; + } + json_object_array_add(my_array, jso); + } + json_object_array_insert_idx(my_array, fdp.ConsumeIntegralInRange(0, 10), + json_object_new_int(fdp.ConsumeIntegral())); + json_object_array_get_idx(my_array, fdp.ConsumeIntegralInRange(0, 10)); + json_object_array_put_idx(my_array, fdp.ConsumeIntegralInRange(0, 10), + json_object_new_int(fdp.ConsumeIntegral())); + json_object_array_del_idx(my_array, fdp.ConsumeIntegralInRange(0, 10), + fdp.ConsumeIntegralInRange(0, 10)); + json_object_array_shrink(my_array, fdp.ConsumeIntegralInRange(0, 10)); + json_object_array_sort(my_array, [](const void *a, const void *b) { return 0; }); + json_object_array_length(my_array); + json_object_put(my_array); + return 0; +} diff --git a/fuzz/json_array_fuzzer.dict b/fuzz/json_array_fuzzer.dict new file mode 100644 index 00000000..ad4e77b5 --- /dev/null +++ b/fuzz/json_array_fuzzer.dict @@ -0,0 +1,21 @@ +"{" +"}" +"," +"[" +"]" +"," +":" +"e" +"e+" +"e-" +"E" +"E+" +"E-" +"\"" +"null" +"1" +"1.234" +"3e4" +"NaN" +"Infinity" +"-Infinity" diff --git a/fuzz/json_object_fuzzer.cc b/fuzz/json_object_fuzzer.cc new file mode 100644 index 00000000..5a697e85 --- /dev/null +++ b/fuzz/json_object_fuzzer.cc @@ -0,0 +1,44 @@ +#include + +#include "json.h" +#include "json_visit.h" + +// Function to test json_c_visit +static int emit_object(json_object *jso, int flags, json_object *parent_jso, const char *jso_key, + size_t *jso_index, void *userarg) { + return JSON_C_VISIT_RETURN_CONTINUE; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + json_object *jso = json_tokener_parse(fdp.ConsumeRandomLengthString(20).c_str()); + + json_object_get_boolean(jso); + json_object_get_double(jso); + json_object_get_int(jso); + json_object_get_int64(jso); + json_object_get_uint64(jso); + json_object_get_string(jso); + json_object_get_string_len(jso); + json_object_get_object(jso); + json_object_get_array(jso); + json_object_get_type(jso); + + json_c_visit(jso, 0, emit_object, NULL); + + json_object_set_int(jso, fdp.ConsumeIntegral()); + json_object_set_int64(jso, fdp.ConsumeIntegral()); + json_object_set_uint64(jso, fdp.ConsumeIntegral()); + json_object_set_double(jso, fdp.ConsumeFloatingPoint()); + json_object_set_string(jso, fdp.ConsumeRandomLengthString(10).c_str()); + json_object_set_boolean(jso, fdp.ConsumeBool()); + std::string str = fdp.ConsumeRandomLengthString(10); + json_object_set_string_len(jso, str.c_str(), str.size()); + + json_object *dst = NULL; + json_object_deep_copy(jso, &dst, json_c_shallow_copy_default); + json_object_put(dst); + + json_object_put(jso); + return 0; +} diff --git a/fuzz/json_object_fuzzer.dict b/fuzz/json_object_fuzzer.dict new file mode 100644 index 00000000..ad4e77b5 --- /dev/null +++ b/fuzz/json_object_fuzzer.dict @@ -0,0 +1,21 @@ +"{" +"}" +"," +"[" +"]" +"," +":" +"e" +"e+" +"e-" +"E" +"E+" +"E-" +"\"" +"null" +"1" +"1.234" +"3e4" +"NaN" +"Infinity" +"-Infinity" diff --git a/fuzz/json_pointer_fuzzer.cc b/fuzz/json_pointer_fuzzer.cc new file mode 100644 index 00000000..809a1479 --- /dev/null +++ b/fuzz/json_pointer_fuzzer.cc @@ -0,0 +1,53 @@ +#include + +#include "json.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + + struct json_tokener *tokener = + json_tokener_new_ex(fdp.ConsumeIntegralInRange(1, JSON_TOKENER_DEFAULT_DEPTH)); + int flags = 0; + if (fdp.ConsumeBool()) { + flags |= JSON_TOKENER_VALIDATE_UTF8; + } + if (fdp.ConsumeBool()) { + flags |= JSON_TOKENER_ALLOW_TRAILING_CHARS; + } + if (fdp.ConsumeBool()) { + flags |= JSON_TOKENER_STRICT; + } + json_tokener_set_flags(tokener, flags); + + std::string path = fdp.ConsumeRandomLengthString(5); + std::string sub_json_str = fdp.ConsumeRandomLengthString(10); + bool use_format_string = fdp.ConsumeBool(); + std::string json_str = fdp.ConsumeRemainingBytesAsString(); + + struct json_object *jo1 = json_tokener_parse_ex(tokener, json_str.c_str(), json_str.size()); + + struct json_object *sub_json = json_tokener_parse(sub_json_str.c_str()); + if (sub_json == NULL) { + sub_json = json_object_new_object(); + } + + struct json_object *jo2 = NULL; + if (use_format_string) { + json_pointer_getf(jo1, &jo2, "%s", path.c_str()); + if (json_pointer_setf(&jo1, sub_json, "%s", path.c_str())) + { + json_object_put(sub_json); + } + } else { + json_pointer_get(jo1, path.c_str(), &jo2); + if (json_pointer_set(&jo1, path.c_str(), sub_json)) + { + json_object_put(sub_json); + } + } + + // Clean up the main JSON object + json_object_put(jo1); + json_tokener_free(tokener); + return 0; +} diff --git a/fuzz/json_pointer_fuzzer.dict b/fuzz/json_pointer_fuzzer.dict new file mode 100644 index 00000000..ad4e77b5 --- /dev/null +++ b/fuzz/json_pointer_fuzzer.dict @@ -0,0 +1,21 @@ +"{" +"}" +"," +"[" +"]" +"," +":" +"e" +"e+" +"e-" +"E" +"E+" +"E-" +"\"" +"null" +"1" +"1.234" +"3e4" +"NaN" +"Infinity" +"-Infinity" diff --git a/fuzz/tokener_parse_ex_fuzzer.dict b/fuzz/tokener_parse_ex_fuzzer.dict index 23c6fa2c..ad4e77b5 100644 --- a/fuzz/tokener_parse_ex_fuzzer.dict +++ b/fuzz/tokener_parse_ex_fuzzer.dict @@ -16,3 +16,6 @@ "1" "1.234" "3e4" +"NaN" +"Infinity" +"-Infinity" -- 2.39.5