diff options
| author | Leitwolf | 2026-10-24 19:03:40 +0300 |
|---|---|---|
| committer | GitHub | 2026-10-24 19:03:40 +0300 |
| commit | 4f1c759cffcb14bd6511e1d7c5fbace682e24f2d (patch) | |
| tree | 415fe5d48a5b48650bba3747beaf245d727c4f61 /fuzzing | |
| parent | 83c6fc3ac13abe83fa39f7b5f8559ccaf4412233 (diff) | |
| parent | 622188f9c08e4af35941c146979883ed4882410e (diff) | |
| download | catch3-4f1c759cffcb14bd6511e1d7c5fbace682e24f2d.tar.gz | |
Merge pull request #15 from Progmasoft/feature/catch3-runner
Replace Catch2's runner with the Catch3 runner
Diffstat (limited to 'fuzzing')
| -rw-r--r-- | fuzzing/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | fuzzing/Progmasoft/fuzz_RunnerJson.cpp | 29 | ||||
| -rw-r--r-- | fuzzing/Progmasoft/fuzz_RunnerOptions.cpp | 50 | ||||
| -rw-r--r-- | fuzzing/fuzz_XmlWriter.cpp | 22 | ||||
| -rw-r--r-- | fuzzing/fuzz_textflow.cpp | 54 |
5 files changed, 88 insertions, 79 deletions
diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 8370fe39..d300a19d 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -7,14 +7,20 @@ 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) +# The runner fuzzers include its C++20 headers. +target_compile_features(fuzzhelper PUBLIC cxx_std_20) # 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) +foreach(fuzzer TestSpecParser) add_executable(fuzz_${fuzzer} fuzz_${fuzzer}.cpp) target_link_libraries(fuzz_${fuzzer} PRIVATE fuzzhelper) endforeach() + +# Progmasoft's fuzzers live apart, under their own license header. +foreach(fuzzer RunnerJson RunnerOptions) + add_executable(fuzz_${fuzzer} Progmasoft/fuzz_${fuzzer}.cpp) + target_link_libraries(fuzz_${fuzzer} PRIVATE fuzzhelper) +endforeach() diff --git a/fuzzing/Progmasoft/fuzz_RunnerJson.cpp b/fuzzing/Progmasoft/fuzz_RunnerJson.cpp new file mode 100644 index 00000000..4cc3770c --- /dev/null +++ b/fuzzing/Progmasoft/fuzz_RunnerJson.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1 + +// The runner reads JSON from its workers, from history files and from +// reports; none of them may crash it. A document that parses must also +// print and parse back to the same text. + +#include <Progmasoft/Runner/Json.hpp> + +#include <cstdint> +#include <cstdlib> +#include <string_view> + +extern "C" int +LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) +{ + const std::string_view text{reinterpret_cast<const char *>(data), size}; + auto parsed = Progmasoft::Catch3::Runner::ParseJson(text); + if (parsed) + { + const auto printed = parsed->ToString(); + auto again = Progmasoft::Catch3::Runner::ParseJson(printed); + if (!again || again->ToString() != printed) + { + std::abort(); + } + } + return 0; +} diff --git a/fuzzing/Progmasoft/fuzz_RunnerOptions.cpp b/fuzzing/Progmasoft/fuzz_RunnerOptions.cpp new file mode 100644 index 00000000..2a10ba91 --- /dev/null +++ b/fuzzing/Progmasoft/fuzz_RunnerOptions.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2026 Progmasoft. +// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1 + +// The command line of a test binary: arguments separated by NUL bytes. The +// parser must answer with options or an error, never crash, and the worker +// arguments it derives must parse again. + +#include <Progmasoft/Runner/Options.hpp> + +#include <cstdint> +#include <cstdlib> +#include <string> +#include <vector> + +extern "C" int +LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) +{ + std::vector<std::string> arguments(1); + for (std::size_t index = 0; index < size; ++index) + { + if (data[index] == 0) + { + arguments.emplace_back(); + } + else + { + arguments.back().push_back(static_cast<char>(data[index])); + } + } + // Reading a file named by --input-file is not what is fuzzed here. + for (const auto &argument : arguments) + { + if (argument.find("input-file") != std::string::npos || + (argument.size() >= 2 && argument[0] == '-' && argument[1] == 'f')) + { + return 0; + } + } + auto options = Progmasoft::Catch3::Runner::ParseOptions(arguments); + if (options) + { + const auto worker = Progmasoft::Catch3::Runner::ParseOptions( + Progmasoft::Catch3::Runner::WorkerArguments(*options)); + if (!worker) + { + std::abort(); + } + } + return 0; +} diff --git a/fuzzing/fuzz_XmlWriter.cpp b/fuzzing/fuzz_XmlWriter.cpp deleted file mode 100644 index 70c4ed80..00000000 --- a/fuzzing/fuzz_XmlWriter.cpp +++ /dev/null @@ -1,22 +0,0 @@ - -// 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 deleted file mode 100644 index f3119379..00000000 --- a/fuzzing/fuzz_textflow.cpp +++ /dev/null @@ -1,54 +0,0 @@ - -// 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> -#include <cstdint> - - -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; -} - |