Skip to content

Commit 6f7c756

Browse files
committed
fuzz: parse the command line arguments in fuzz tests
Retrieve the command line arguments from the fuzzer and save them for later retrieval by `BasicTestingSetup` so that we gain extra flexibility of passing any config options on the test command line, e.g.: ``` FUZZ=addrman ./src/test/fuzz/fuzz --checkaddrman=5 ``` A fuzz test should call `MakeNoLogFileContext<>()` in its initialize function in order to invoke the constructor of `BasicTestingSetup`, which sets `gArgs`.
1 parent 92a0f7e commit 6f7c756

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

doc/fuzzing.md

+9
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ block^@M-^?M-^?M-^?M-^?M-^?nM-^?M-^?
7171
7272
In this case the fuzzer managed to create a `block` message which when passed to `ProcessMessage(...)` increased coverage.
7373
74+
It is possible to specify `bitcoind` arguments to the `fuzz` executable.
75+
Depending on the test, they may be ignored or consumed and alter the behavior
76+
of the test. Just make sure to use double-dash to distinguish them from the
77+
fuzzer's own arguments:
78+
79+
```sh
80+
$ FUZZ=address_deserialize_v2 src/test/fuzz/fuzz -runs=1 fuzz_seed_corpus/address_deserialize_v2 --checkaddrman=5 --printtoconsole=1
81+
```
82+
7483
## Fuzzing corpora
7584
7685
The project's collection of seed corpora is found in the [`bitcoin-core/qa-assets`](https://github.com/bitcoin-core/qa-assets) repo.

src/test/fuzz/fuzz.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,28 @@
2020

2121
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
2222

23-
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
23+
/**
24+
* A copy of the command line arguments that start with `--`.
25+
* First `LLVMFuzzerInitialize()` is called, which saves the arguments to `g_args`.
26+
* Later, depending on the fuzz test, `G_TEST_COMMAND_LINE_ARGUMENTS()` may be
27+
* called by `BasicTestingSetup` constructor to fetch those arguments and store
28+
* them in `BasicTestingSetup::m_node::args`.
29+
*/
30+
static std::vector<const char*> g_args;
31+
32+
static void SetArgs(int argc, char** argv) {
33+
for (int i = 1; i < argc; ++i) {
34+
// Only take into account arguments that start with `--`. The others are for the fuzz engine:
35+
// `fuzz -runs=1 fuzz_seed_corpus/address_deserialize_v2 --checkaddrman=5`
36+
if (strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == '-') {
37+
g_args.push_back(argv[i]);
38+
}
39+
}
40+
}
41+
42+
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS = []() {
43+
return g_args;
44+
};
2445

2546
std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize, TypeHidden>>& FuzzTargets()
2647
{
@@ -98,6 +119,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
98119
// This function is used by libFuzzer
99120
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
100121
{
122+
SetArgs(*argc, *argv);
101123
initialize();
102124
return 0;
103125
}

0 commit comments

Comments
 (0)