diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 44ba8bc2542..c20cbde05f1 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -54,20 +54,25 @@ const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS = return g_args; }; -std::map>& FuzzTargets() +struct FuzzTarget { + const TypeTestOneInput test_one_input; + const FuzzTargetOptions opts; +}; + +auto& FuzzTargets() { - static std::map> g_fuzz_targets; + static std::map g_fuzz_targets; return g_fuzz_targets; } -void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden) +void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts) { - const auto it_ins = FuzzTargets().try_emplace(name, std::move(target), std::move(init), hidden); + const auto it_ins{FuzzTargets().try_emplace(name, FuzzTarget /* temporary can be dropped in C++20 */ {std::move(target), std::move(opts)})}; Assert(it_ins.second); } static std::string_view g_fuzz_target; -static TypeTestOneInput* g_test_one_input{nullptr}; +static const TypeTestOneInput* g_test_one_input{nullptr}; void initialize() { @@ -84,22 +89,22 @@ void initialize() bool should_exit{false}; if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) { - for (const auto& t : FuzzTargets()) { - if (std::get<2>(t.second)) continue; - std::cout << t.first << std::endl; + for (const auto& [name, t] : FuzzTargets()) { + if (t.opts.hidden) continue; + std::cout << name << std::endl; } should_exit = true; } if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) { std::cout << "Writing all fuzz target names to '" << out_path << "'." << std::endl; std::ofstream out_stream{out_path, std::ios::binary}; - for (const auto& t : FuzzTargets()) { - if (std::get<2>(t.second)) continue; - out_stream << t.first << std::endl; + for (const auto& [name, t] : FuzzTargets()) { + if (t.opts.hidden) continue; + out_stream << name << std::endl; } - should_exit= true; + should_exit = true; } - if (should_exit){ + if (should_exit) { std::exit(EXIT_SUCCESS); } if (const auto* env_fuzz{std::getenv("FUZZ")}) { @@ -117,8 +122,8 @@ void initialize() std::exit(EXIT_FAILURE); } Assert(!g_test_one_input); - g_test_one_input = &std::get<0>(it->second); - std::get<1>(it->second)(); + g_test_one_input = &it->second.test_one_input; + it->second.opts.init(); } #if defined(PROVIDE_FUZZ_MAIN_FUNCTION) diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index c91c33da670..18ebbda2140 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -21,25 +21,28 @@ using FuzzBufferType = Span; using TypeTestOneInput = std::function; -using TypeInitialize = std::function; -using TypeHidden = bool; +struct FuzzTargetOptions { + std::function init{[] {}}; + bool hidden{false}; +}; -void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden); +void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts); -inline void FuzzFrameworkEmptyInitFun() {} - -#define FUZZ_TARGET(name) \ - FUZZ_TARGET_INIT(name, FuzzFrameworkEmptyInitFun) +#if defined(__clang__) +#define FUZZ_TARGET(...) _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") DETAIL_FUZZ(__VA_ARGS__) _Pragma("clang diagnostic pop") +#else +#define FUZZ_TARGET(...) DETAIL_FUZZ(__VA_ARGS__) +#endif #define FUZZ_TARGET_INIT(name, init_fun) \ - FUZZ_TARGET_INIT_HIDDEN(name, init_fun, false) + FUZZ_TARGET(name, .init = init_fun) -#define FUZZ_TARGET_INIT_HIDDEN(name, init_fun, hidden) \ +#define DETAIL_FUZZ(name, ...) \ void name##_fuzz_target(FuzzBufferType); \ struct name##_Before_Main { \ name##_Before_Main() \ { \ - FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, init_fun, hidden); \ + FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, {__VA_ARGS__}); \ } \ } const static g_##name##_before_main; \ void name##_fuzz_target(FuzzBufferType buffer) diff --git a/src/test/fuzz/script_assets_test_minimizer.cpp b/src/test/fuzz/script_assets_test_minimizer.cpp index 206d219afe3..7862be2f213 100644 --- a/src/test/fuzz/script_assets_test_minimizer.cpp +++ b/src/test/fuzz/script_assets_test_minimizer.cpp @@ -186,7 +186,7 @@ void Test(const std::string& str) void test_init() {} -FUZZ_TARGET_INIT_HIDDEN(script_assets_test_minimizer, test_init, /*hidden=*/true) +FUZZ_TARGET(script_assets_test_minimizer, .init = test_init, .hidden = true) { if (buffer.size() < 2 || buffer.back() != '\n' || buffer[buffer.size() - 2] != ',') return; const std::string str((const char*)buffer.data(), buffer.size() - 2);