mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-12 01:42:01 +02:00
fuzz: Accept options in FUZZ_TARGET macro
* This allows to reduce the number of total macros. * Also, adding a new option no longer requires doubling the number of macros in the worst case.
This commit is contained in:
parent
357e3f6aa4
commit
fa36ad8b09
@ -54,20 +54,25 @@ const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS =
|
||||
return g_args;
|
||||
};
|
||||
|
||||
std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>>& FuzzTargets()
|
||||
struct FuzzTarget {
|
||||
const TypeTestOneInput test_one_input;
|
||||
const FuzzTargetOptions opts;
|
||||
};
|
||||
|
||||
auto& FuzzTargets()
|
||||
{
|
||||
static std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>> g_fuzz_targets;
|
||||
static std::map<std::string_view, FuzzTarget> 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)
|
||||
|
@ -21,25 +21,28 @@
|
||||
using FuzzBufferType = Span<const uint8_t>;
|
||||
|
||||
using TypeTestOneInput = std::function<void(FuzzBufferType)>;
|
||||
using TypeInitialize = std::function<void()>;
|
||||
using TypeHidden = bool;
|
||||
struct FuzzTargetOptions {
|
||||
std::function<void()> 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)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user