diff --git a/.github/workflows/fuzzers.yml b/.github/workflows/fuzzers.yml index 9db22554..8e2c83f5 100644 --- a/.github/workflows/fuzzers.yml +++ b/.github/workflows/fuzzers.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: ubuntu-latest env: - allfuzzers: parser dump + allfuzzers: parser dump dump_raw_tape print_json artifactsprefix: -artifact_prefix=fuzzfailure/ steps: - name: Install packages necessary for building diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index c8c3cc55..d30c38a4 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -29,6 +29,12 @@ set(SOURCES fuzz_parser.cpp # fuzz_minify.cpp # <--- does not pass the build check test on oss-fuzz, says "partially instrumented". help needed! fuzz_dump.cpp + fuzz_print_json.cpp + fuzz_dump_raw_tape.cpp +) + +add_custom_target(print_all_fuzz_targets + COMMAND ${CMAKE_COMMAND} -E echo ${SOURCES} ) macro(implement_fuzzer sourcefile) diff --git a/fuzz/NullBuffer.h b/fuzz/NullBuffer.h new file mode 100644 index 00000000..f87452a2 --- /dev/null +++ b/fuzz/NullBuffer.h @@ -0,0 +1,21 @@ + +#pragma once + +#include + +// from https://stackoverflow.com/a/8244052 +class NulStreambuf : public std::streambuf { + char dummyBuffer[64]; + +protected: + virtual int overflow(int c) override final{ + setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer)); + return (c == traits_type::eof()) ? '\0' : c; + } +}; + +class NulOStream final : private NulStreambuf, public std::ostream { +public: + NulOStream() : std::ostream(this) {} + NulStreambuf *rdbuf() { return this; } +}; diff --git a/fuzz/build_fuzzer_variants.sh b/fuzz/build_fuzzer_variants.sh index 59c42203..6fc1afb6 100755 --- a/fuzz/build_fuzzer_variants.sh +++ b/fuzz/build_fuzzer_variants.sh @@ -10,6 +10,8 @@ set -eu unset CXX CC CFLAGS CXXFLAGS LDFLAGS +me=$(basename $0) + # A reproduce build, without avx but otherwise as plain # as it gets. No sanitizers or optimization. variant=plain-noavx @@ -76,28 +78,32 @@ fi # a fuzzer with sanitizers, built with avx disabled. variant=ossfuzz-noavx8 -if [ ! -d build-$variant ] ; then - - export CC=clang-8 - export CXX="clang++-8" - export CFLAGS="-fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined -mno-avx2 -mno-avx " - export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined -mno-avx2 -mno-avx" - export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" - - mkdir build-$variant - cd build-$variant - - cmake .. \ - -GNinja \ - -DCMAKE_BUILD_TYPE=Debug \ - -DSIMDJSON_BUILD_STATIC=On \ - -DENABLE_FUZZING=On \ - -DSIMDJSON_FUZZ_LINKMAIN=Off \ - -DSIMDJSON_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE \ - -DSIMDJSON_DISABLE_AVX=On - - ninja - cd .. +if which clang++-8 >/dev/null 2>&1 ; then + if [ ! -d build-$variant ] ; then + + export CC=clang-8 + export CXX="clang++-8" + export CFLAGS="-fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined -mno-avx2 -mno-avx " + export CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -fno-sanitize-recover=undefined -mno-avx2 -mno-avx" + export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + + mkdir build-$variant + cd build-$variant + + cmake .. \ + -GNinja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DSIMDJSON_BUILD_STATIC=On \ + -DENABLE_FUZZING=On \ + -DSIMDJSON_FUZZ_LINKMAIN=Off \ + -DSIMDJSON_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE \ + -DSIMDJSON_DISABLE_AVX=On + + ninja + cd .. + fi +else + echo "$me: WARNING clang++-8 not found, please install it to build $variant" fi # a fuzzer with sanitizers, default built @@ -127,25 +133,30 @@ fi # a fast fuzzer, for fast exploration variant=ossfuzz-fast8 -if [ ! -d build-$variant ] ; then - export CC=clang-8 - export CXX="clang++-8" - export CFLAGS="-fsanitize=fuzzer-no-link -O3 -g" - export CXXFLAGS="-fsanitize=fuzzer-no-link -O3 -g" - export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" - - mkdir build-$variant - cd build-$variant - - cmake .. \ - -GNinja \ - -DCMAKE_BUILD_TYPE= \ - -DSIMDJSON_BUILD_STATIC=On \ - -DENABLE_FUZZING=On \ - -DSIMDJSON_FUZZ_LINKMAIN=Off \ - -DSIMDJSON_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE - - ninja - - cd .. +if which clang++-8 >/dev/null 2>&1 ; then + if [ ! -d build-$variant ] ; then + export CC=clang-8 + export CXX="clang++-8" + export CFLAGS="-fsanitize=fuzzer-no-link -O3 -g" + export CXXFLAGS="-fsanitize=fuzzer-no-link -O3 -g" + export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + + mkdir build-$variant + cd build-$variant + + cmake .. \ + -GNinja \ + -DCMAKE_BUILD_TYPE= \ + -DSIMDJSON_BUILD_STATIC=On \ + -DENABLE_FUZZING=On \ + -DSIMDJSON_FUZZ_LINKMAIN=Off \ + -DSIMDJSON_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE + + ninja + + cd .. + fi +else + echo "$me: WARNING clang++-8 not found, please install it to build $variant" fi + diff --git a/fuzz/fuzz_dump.cpp b/fuzz/fuzz_dump.cpp index e842c43c..831a15c6 100644 --- a/fuzz/fuzz_dump.cpp +++ b/fuzz/fuzz_dump.cpp @@ -4,22 +4,7 @@ #include #include -// from https://stackoverflow.com/a/8244052 -class NulStreambuf : public std::streambuf { - char dummyBuffer[64]; - -protected: - virtual int overflow(int c) { - setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer)); - return (c == traits_type::eof()) ? '\0' : c; - } -}; - -class NulOStream : private NulStreambuf, public std::ostream { -public: - NulOStream() : std::ostream(this) {} - NulStreambuf *rdbuf() { return this; } -}; +#include "NullBuffer.h" // from the README on the front page void compute_dump(simdjson::ParsedJson::Iterator &pjh) { diff --git a/fuzz/fuzz_dump_raw_tape.cpp b/fuzz/fuzz_dump_raw_tape.cpp new file mode 100644 index 00000000..6a861f4a --- /dev/null +++ b/fuzz/fuzz_dump_raw_tape.cpp @@ -0,0 +1,18 @@ +#include "simdjson/jsonparser.h" +#include +#include +#include +#include + +#include "NullBuffer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + try { + auto pj = simdjson::build_parsed_json(Data, Size); + NulOStream os; + bool ignored=pj.dump_raw_tape(os); + } catch (...) { + } + return 0; +} diff --git a/fuzz/fuzz_print_json.cpp b/fuzz/fuzz_print_json.cpp new file mode 100644 index 00000000..4961e084 --- /dev/null +++ b/fuzz/fuzz_print_json.cpp @@ -0,0 +1,19 @@ +#include "simdjson/jsonparser.h" +#include +#include +#include + +#include "NullBuffer.h" + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + try { + auto pj = simdjson::build_parsed_json(Data, Size); + NulOStream os; + bool ignored=pj.print_json(os); + (void)ignored; + } catch (...) { + } + return 0; +} diff --git a/fuzz/measure_coverage.sh b/fuzz/measure_coverage.sh new file mode 100755 index 00000000..b6eab920 --- /dev/null +++ b/fuzz/measure_coverage.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# makes a coverage build. +# +# To measure and display the coverage: +# +#cd build-coverage +#fuzz/fuzz_parser path/to/corpus/* # repeat with other fuzzers +#gcovr -r . --html --html-details --sort-uncovered -o out.html +# and view the results in out.html + +bdir=build-coverage +if [ ! -d $bdir ] ; then + mkdir -p $bdir + cd $bdir + + export CC=gcc + export CXX="g++" + export CFLAGS="-fprofile-arcs -ftest-coverage" + export CXXFLAGS="-fprofile-arcs -ftest-coverage" + export LDFLAGS="-fprofile-arcs -ftest-coverage" + + cmake .. \ + -GNinja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DSIMDJSON_BUILD_STATIC=On \ + -DENABLE_FUZZING=On \ + -DSIMDJSON_FUZZ_LINKMAIN=On + ninja + cd .. +fi + + +