From 725ca010e7f09ce2575f6a9521b35b59257f813a Mon Sep 17 00:00:00 2001 From: Paul Dreik Date: Tue, 1 Dec 2020 21:58:41 +0100 Subject: [PATCH] add ndjson fuzzer (#1304) * add ndjson fuzzer * reproduce #1310 in the newly added unit test Had to replace the input, because: 1) the fuzzer uses the first part of the input to determine the batch_size to use, so that has to be cut off 2) the master now protects against low values of batch_size I also made the test not return early, so the error is triggered. --- .github/workflows/fuzzers.yml | 2 +- fuzz/CMakeLists.txt | 1 + fuzz/FuzzUtils.h | 8 ++++++++ fuzz/fuzz_ndjson.cpp | 31 +++++++++++++++++++++++++++++++ fuzz/ossfuzz.sh | 1 - 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 fuzz/fuzz_ndjson.cpp diff --git a/.github/workflows/fuzzers.yml b/.github/workflows/fuzzers.yml index 1d74c52c5..4cc99c135 100644 --- a/.github/workflows/fuzzers.yml +++ b/.github/workflows/fuzzers.yml @@ -17,7 +17,7 @@ jobs: # fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json # fuzzers that loop over the implementations themselves, or don't need to switch. - implfuzzers: implementations minifyimpl ondemand padded utf8 + implfuzzers: implementations minifyimpl ndjson ondemand padded utf8 implementations: haswell westmere fallback UBSAN_OPTIONS: halt_on_error=1 MAXLEN: -max_len=4000 diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index fc6a390d0..25b11016d 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -57,6 +57,7 @@ if(ENABLE_FUZZING) implement_fuzzer(fuzz_implementations) # parses and serializes again, compares across implementations implement_fuzzer(fuzz_minify) # minify *with* parsing implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations + implement_fuzzer(fuzz_ndjson) # the ndjson api implement_fuzzer(fuzz_ondemand) implement_fuzzer(fuzz_padded) implement_fuzzer(fuzz_parser) diff --git a/fuzz/FuzzUtils.h b/fuzz/FuzzUtils.h index 22594337f..b9a05e8fc 100644 --- a/fuzz/FuzzUtils.h +++ b/fuzz/FuzzUtils.h @@ -105,6 +105,14 @@ struct FuzzData { return {}; } + // consumes the rest of the data as a string view + std::string_view remainder_as_stringview() { + std::string_view ret{chardata(),Size}; + Data+=Size; + Size=0; + return ret; + } + // split the remainder of the data into string views, std::vector splitIntoStrings() { std::vector ret; diff --git a/fuzz/fuzz_ndjson.cpp b/fuzz/fuzz_ndjson.cpp new file mode 100644 index 000000000..d7bce179b --- /dev/null +++ b/fuzz/fuzz_ndjson.cpp @@ -0,0 +1,31 @@ +#include "simdjson.h" +#include +#include +#include + +#include "FuzzUtils.h" +#include "NullBuffer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + FuzzData fd(Data, Size); + const auto batch_size=static_cast(fd.getInt<0,1000>()); + const auto json=simdjson::padded_string{fd.remainder_as_stringview()}; + simdjson::dom::parser parser; +#if SIMDJSON_EXCEPTIONS + try { +#endif + simdjson::dom::document_stream docs; + if(parser.parse_many(json,batch_size).get(docs)) { + return 0; + } + + size_t bool_count=0; + for (auto doc : docs) { + bool_count+=doc.is_bool(); + } +#if SIMDJSON_EXCEPTIONS + } catch(...) { + } +#endif + return 0; +} diff --git a/fuzz/ossfuzz.sh b/fuzz/ossfuzz.sh index 4b6d71c07..b4cf9e7bd 100755 --- a/fuzz/ossfuzz.sh +++ b/fuzz/ossfuzz.sh @@ -30,7 +30,6 @@ cmake .. \ -DENABLE_FUZZING=On \ -DSIMDJSON_COMPETITION=Off \ -DSIMDJSON_FUZZ_LINKMAIN=Off \ --DSIMDJSON_GIT=Off \ -DSIMDJSON_GOOGLE_BENCHMARKS=Off \ -DSIMDJSON_DISABLE_DEPRECATED_API=On \ -DSIMDJSON_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE