diff options
Diffstat (limited to 'fuzzing')
| -rw-r--r-- | fuzzing/CMakeLists.txt | 20 | ||||
| -rw-r--r-- | fuzzing/NullOStream.cpp | 18 | ||||
| -rw-r--r-- | fuzzing/NullOStream.h | 28 | ||||
| -rwxr-xr-x | fuzzing/build_fuzzers.sh | 33 | ||||
| -rw-r--r-- | fuzzing/fuzz_TestSpecParser.cpp | 22 | ||||
| -rw-r--r-- | fuzzing/fuzz_XmlWriter.cpp | 22 | ||||
| -rw-r--r-- | fuzzing/fuzz_textflow.cpp | 53 |
7 files changed, 196 insertions, 0 deletions
diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt new file mode 100644 index 0000000..daba61d --- /dev/null +++ b/fuzzing/CMakeLists.txt @@ -0,0 +1,20 @@ +# License: Boost 1.0 +# By Paul Dreik 2020 + +# add a library that brings in the main() function from libfuzzer +# and has all the dependencies, so the individual fuzzers can be +# added one line each. +add_library(fuzzhelper NullOStream.h NullOStream.cpp) +target_link_libraries(fuzzhelper PUBLIC Catch2::Catch2) + +# use C++17 so we can get string_view +target_compile_features(fuzzhelper PUBLIC cxx_std_17) + +# This should be possible to set from the outside to be oss-fuzz compatible, +# fix later. For now, target libFuzzer only. +target_link_options(fuzzhelper PUBLIC "-fsanitize=fuzzer") + +foreach(fuzzer TestSpecParser XmlWriter textflow) +add_executable(fuzz_${fuzzer} fuzz_${fuzzer}.cpp) +target_link_libraries(fuzz_${fuzzer} PRIVATE fuzzhelper) +endforeach() diff --git a/fuzzing/NullOStream.cpp b/fuzzing/NullOStream.cpp new file mode 100644 index 0000000..e3a181e --- /dev/null +++ b/fuzzing/NullOStream.cpp @@ -0,0 +1,18 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include "NullOStream.h" + +void NullOStream::avoidOutOfLineVirtualCompilerWarning() +{ +} + +int NullStreambuf::overflow(int c){ + setp(dummyBuffer, dummyBuffer + sizeof(dummyBuffer)); + return (c == traits_type::eof()) ? '\0' : c; +} diff --git a/fuzzing/NullOStream.h b/fuzzing/NullOStream.h new file mode 100644 index 0000000..abbec09 --- /dev/null +++ b/fuzzing/NullOStream.h @@ -0,0 +1,28 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#pragma once + +#include <ostream> +#include <streambuf> + +// from https://stackoverflow.com/a/8244052 +class NullStreambuf : public std::streambuf { + char dummyBuffer[64]; + +protected: + virtual int overflow(int c) override final; +}; + +class NullOStream final : private NullStreambuf, public std::ostream { +public: + NullOStream() : std::ostream(this) {} + NullStreambuf *rdbuf() { return this; } + virtual void avoidOutOfLineVirtualCompilerWarning(); +}; + diff --git a/fuzzing/build_fuzzers.sh b/fuzzing/build_fuzzers.sh new file mode 100755 index 0000000..9788c68 --- /dev/null +++ b/fuzzing/build_fuzzers.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Builds the fuzzers +# +# By Paul Dreik 20200923 +set -exu + +CATCHROOT=$(readlink -f $(dirname $0)/..) + + +BUILDDIR=$CATCHROOT/build-fuzzers +mkdir -p $BUILDDIR +cd $BUILDDIR + +if which /usr/lib/ccache/clang++ >/dev/null 2>&1 ; then + CXX=/usr/lib/ccache/clang++ +else + CXX=clang++ +fi + +cmake $CATCHROOT \ + -DCMAKE_CXX_COMPILER=$CXX \ + -DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link,address,undefined -O3 -g" \ + -DCATCH_DEVELOPMENT_BUILD=On \ + -DCATCH_BUILD_EXAMPLES=Off \ + -DCATCH_BUILD_EXTRA_TESTS=Off \ + -DCATCH_BUILD_TESTING=Off \ + -DBUILD_TESTING=Off \ + -DCATCH_ENABLE_WERROR=Off \ + -DCATCH_BUILD_FUZZERS=On + +cmake --build . -j $(nproc) + diff --git a/fuzzing/fuzz_TestSpecParser.cpp b/fuzzing/fuzz_TestSpecParser.cpp new file mode 100644 index 0000000..3aba8c8 --- /dev/null +++ b/fuzzing/fuzz_TestSpecParser.cpp @@ -0,0 +1,22 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +//By Paul Dreik 2020 + +#include <catch2/internal/catch_test_spec_parser.hpp> +#include <catch2/internal/catch_tag_alias_registry.hpp> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + Catch::TagAliasRegistry tar; + Catch::TestSpecParser tsp(tar); + + std::string buf(Data,Data+Size); + tsp.parse(buf); + + return 0; +} diff --git a/fuzzing/fuzz_XmlWriter.cpp b/fuzzing/fuzz_XmlWriter.cpp new file mode 100644 index 0000000..70c4ed8 --- /dev/null +++ b/fuzzing/fuzz_XmlWriter.cpp @@ -0,0 +1,22 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +//By Paul Dreik 2020 + +#include <catch2/internal/catch_xmlwriter.hpp> + +#include "NullOStream.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + std::string buf(Data,Data+Size); + NullOStream nul; + Catch::XmlEncode encode(buf); + encode.encodeTo(nul); + return 0; +} + diff --git a/fuzzing/fuzz_textflow.cpp b/fuzzing/fuzz_textflow.cpp new file mode 100644 index 0000000..7000f42 --- /dev/null +++ b/fuzzing/fuzz_textflow.cpp @@ -0,0 +1,53 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +//By Paul Dreik 2020 + +#include <catch2/internal/catch_textflow.hpp> + +#include "NullOStream.h" + +#include <string> +#include <string_view> + + +template<class Callback> +void split(const char *Data, size_t Size, Callback callback) { + + using namespace std::literals; + constexpr auto sep="\n~~~\n"sv; + + std::string_view remainder(Data,Size); + for (;;) { + auto pos=remainder.find(sep); + if(pos==std::string_view::npos) { + //not found. use the remainder and exit + callback(remainder); + return; + } else { + //found. invoke callback on the first part, then proceed with the rest. + callback(remainder.substr(0,pos)); + remainder=remainder.substr(pos+sep.size()); + } + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + Catch::TextFlow::Columns columns; + + // break the input on separator + split((const char*)Data,Size,[&](std::string_view word) { + columns+=Catch::TextFlow::Column(std::string(word)); + }); + + NullOStream nul; + nul << columns; + + return 0; +} + |
