Skip to content

Commit fa36ad8

Browse files
author
MarcoFalke
committed
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.
1 parent 357e3f6 commit fa36ad8

File tree

3 files changed

+34
-26
lines changed

3 files changed

+34
-26
lines changed

src/test/fuzz/fuzz.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,25 @@ const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS =
5454
return g_args;
5555
};
5656

57-
std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>>& FuzzTargets()
57+
struct FuzzTarget {
58+
const TypeTestOneInput test_one_input;
59+
const FuzzTargetOptions opts;
60+
};
61+
62+
auto& FuzzTargets()
5863
{
59-
static std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>> g_fuzz_targets;
64+
static std::map<std::string_view, FuzzTarget> g_fuzz_targets;
6065
return g_fuzz_targets;
6166
}
6267

63-
void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden)
68+
void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts)
6469
{
65-
const auto it_ins = FuzzTargets().try_emplace(name, std::move(target), std::move(init), hidden);
70+
const auto it_ins{FuzzTargets().try_emplace(name, FuzzTarget /* temporary can be dropped in C++20 */ {std::move(target), std::move(opts)})};
6671
Assert(it_ins.second);
6772
}
6873

6974
static std::string_view g_fuzz_target;
70-
static TypeTestOneInput* g_test_one_input{nullptr};
75+
static const TypeTestOneInput* g_test_one_input{nullptr};
7176

7277
void initialize()
7378
{
@@ -84,22 +89,22 @@ void initialize()
8489

8590
bool should_exit{false};
8691
if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) {
87-
for (const auto& t : FuzzTargets()) {
88-
if (std::get<2>(t.second)) continue;
89-
std::cout << t.first << std::endl;
92+
for (const auto& [name, t] : FuzzTargets()) {
93+
if (t.opts.hidden) continue;
94+
std::cout << name << std::endl;
9095
}
9196
should_exit = true;
9297
}
9398
if (const char* out_path = std::getenv("WRITE_ALL_FUZZ_TARGETS_AND_ABORT")) {
9499
std::cout << "Writing all fuzz target names to '" << out_path << "'." << std::endl;
95100
std::ofstream out_stream{out_path, std::ios::binary};
96-
for (const auto& t : FuzzTargets()) {
97-
if (std::get<2>(t.second)) continue;
98-
out_stream << t.first << std::endl;
101+
for (const auto& [name, t] : FuzzTargets()) {
102+
if (t.opts.hidden) continue;
103+
out_stream << name << std::endl;
99104
}
100-
should_exit= true;
105+
should_exit = true;
101106
}
102-
if (should_exit){
107+
if (should_exit) {
103108
std::exit(EXIT_SUCCESS);
104109
}
105110
if (const auto* env_fuzz{std::getenv("FUZZ")}) {
@@ -117,8 +122,8 @@ void initialize()
117122
std::exit(EXIT_FAILURE);
118123
}
119124
Assert(!g_test_one_input);
120-
g_test_one_input = &std::get<0>(it->second);
121-
std::get<1>(it->second)();
125+
g_test_one_input = &it->second.test_one_input;
126+
it->second.opts.init();
122127
}
123128

124129
#if defined(PROVIDE_FUZZ_MAIN_FUNCTION)

src/test/fuzz/fuzz.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,28 @@
2121
using FuzzBufferType = Span<const uint8_t>;
2222

2323
using TypeTestOneInput = std::function<void(FuzzBufferType)>;
24-
using TypeInitialize = std::function<void()>;
25-
using TypeHidden = bool;
24+
struct FuzzTargetOptions {
25+
std::function<void()> init{[] {}};
26+
bool hidden{false};
27+
};
2628

27-
void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init, TypeHidden hidden);
29+
void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, FuzzTargetOptions opts);
2830

29-
inline void FuzzFrameworkEmptyInitFun() {}
30-
31-
#define FUZZ_TARGET(name) \
32-
FUZZ_TARGET_INIT(name, FuzzFrameworkEmptyInitFun)
31+
#if defined(__clang__)
32+
#define FUZZ_TARGET(...) _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") DETAIL_FUZZ(__VA_ARGS__) _Pragma("clang diagnostic pop")
33+
#else
34+
#define FUZZ_TARGET(...) DETAIL_FUZZ(__VA_ARGS__)
35+
#endif
3336

3437
#define FUZZ_TARGET_INIT(name, init_fun) \
35-
FUZZ_TARGET_INIT_HIDDEN(name, init_fun, false)
38+
FUZZ_TARGET(name, .init = init_fun)
3639

37-
#define FUZZ_TARGET_INIT_HIDDEN(name, init_fun, hidden) \
40+
#define DETAIL_FUZZ(name, ...) \
3841
void name##_fuzz_target(FuzzBufferType); \
3942
struct name##_Before_Main { \
4043
name##_Before_Main() \
4144
{ \
42-
FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, init_fun, hidden); \
45+
FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, {__VA_ARGS__}); \
4346
} \
4447
} const static g_##name##_before_main; \
4548
void name##_fuzz_target(FuzzBufferType buffer)

src/test/fuzz/script_assets_test_minimizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ void Test(const std::string& str)
186186

187187
void test_init() {}
188188

189-
FUZZ_TARGET_INIT_HIDDEN(script_assets_test_minimizer, test_init, /*hidden=*/true)
189+
FUZZ_TARGET(script_assets_test_minimizer, .init = test_init, .hidden = true)
190190
{
191191
if (buffer.size() < 2 || buffer.back() != '\n' || buffer[buffer.size() - 2] != ',') return;
192192
const std::string str((const char*)buffer.data(), buffer.size() - 2);

0 commit comments

Comments
 (0)