From 5da14042f70711ea5cf66e034699730335462f66 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 5 May 2024 14:08:03 +0200 Subject: Merging upstream version 1.45.3+dfsg. Signed-off-by: Daniel Baumann --- .../test/ossfuzz/json_load_dump_fuzzer.cc | 132 +++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc (limited to 'src/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc') diff --git a/src/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc b/src/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc new file mode 100644 index 000000000..bc3844e75 --- /dev/null +++ b/src/fluent-bit/lib/jansson-e23f558/test/ossfuzz/json_load_dump_fuzzer.cc @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +#include "jansson.h" + +static int enable_diags; + +#define FUZZ_DEBUG(FMT, ...) \ + if (enable_diags) \ + { \ + fprintf(stderr, FMT, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } + + +static int json_dump_counter(const char *buffer, size_t size, void *data) +{ + uint64_t *counter = reinterpret_cast(data); + *counter += size; + return 0; +} + + +#define NUM_COMMAND_BYTES (sizeof(size_t) + sizeof(size_t) + 1) + +#define FUZZ_DUMP_CALLBACK 0x00 +#define FUZZ_DUMP_STRING 0x01 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + json_error_t error; + unsigned char dump_mode; + + // Enable or disable diagnostics based on the FUZZ_VERBOSE environment flag. + enable_diags = (getenv("FUZZ_VERBOSE") != NULL); + + FUZZ_DEBUG("Input data length: %zd", size); + + if (size < NUM_COMMAND_BYTES) + { + return 0; + } + + // Use the first sizeof(size_t) bytes as load flags. + size_t load_flags = *(const size_t*)data; + data += sizeof(size_t); + + FUZZ_DEBUG("load_flags: 0x%zx\n" + "& JSON_REJECT_DUPLICATES = 0x%zx\n" + "& JSON_DECODE_ANY = 0x%zx\n" + "& JSON_DISABLE_EOF_CHECK = 0x%zx\n" + "& JSON_DECODE_INT_AS_REAL = 0x%zx\n" + "& JSON_ALLOW_NUL = 0x%zx\n", + load_flags, + load_flags & JSON_REJECT_DUPLICATES, + load_flags & JSON_DECODE_ANY, + load_flags & JSON_DISABLE_EOF_CHECK, + load_flags & JSON_DECODE_INT_AS_REAL, + load_flags & JSON_ALLOW_NUL); + + // Use the next sizeof(size_t) bytes as dump flags. + size_t dump_flags = *(const size_t*)data; + data += sizeof(size_t); + + FUZZ_DEBUG("dump_flags: 0x%zx\n" + "& JSON_MAX_INDENT = 0x%zx\n" + "& JSON_COMPACT = 0x%zx\n" + "& JSON_ENSURE_ASCII = 0x%zx\n" + "& JSON_SORT_KEYS = 0x%zx\n" + "& JSON_PRESERVE_ORDER = 0x%zx\n" + "& JSON_ENCODE_ANY = 0x%zx\n" + "& JSON_ESCAPE_SLASH = 0x%zx\n" + "& JSON_REAL_PRECISION = 0x%zx\n" + "& JSON_EMBED = 0x%zx\n", + dump_flags, + dump_flags & JSON_MAX_INDENT, + dump_flags & JSON_COMPACT, + dump_flags & JSON_ENSURE_ASCII, + dump_flags & JSON_SORT_KEYS, + dump_flags & JSON_PRESERVE_ORDER, + dump_flags & JSON_ENCODE_ANY, + dump_flags & JSON_ESCAPE_SLASH, + ((dump_flags >> 11) & 0x1F) << 11, + dump_flags & JSON_EMBED); + + // Use the next byte as the dump mode. + dump_mode = data[0]; + data++; + + FUZZ_DEBUG("dump_mode: 0x%x", (unsigned int)dump_mode); + + // Remove the command bytes from the size total. + size -= NUM_COMMAND_BYTES; + + // Attempt to load the remainder of the data with the given load flags. + const char* text = reinterpret_cast(data); + json_t* jobj = json_loadb(text, size, load_flags, &error); + + if (jobj == NULL) + { + return 0; + } + + if (dump_mode & FUZZ_DUMP_STRING) + { + // Dump as a string. Remove indents so that we don't run out of memory. + char *out = json_dumps(jobj, dump_flags & ~JSON_MAX_INDENT); + if (out != NULL) + { + free(out); + } + } + else + { + // Default is callback mode. + // + // Attempt to dump the loaded json object with the given dump flags. + uint64_t counter = 0; + + json_dump_callback(jobj, json_dump_counter, &counter, dump_flags); + FUZZ_DEBUG("Counter function counted %" PRIu64 " bytes.", counter); + } + + if (jobj) + { + json_decref(jobj); + } + + return 0; +} -- cgit v1.2.3