Skip to content

Commit 3b5b276

Browse files
author
MarcoFalke
committed
Merge #17942: doc: Improve fuzzing docs for macOS users
b6c3e84 doc: Improve fuzzing docs for macOS users (Fabian Jahr) Pull request description: Adds several helpful hints for macOS users trying to get fuzzers to run locally using AFL or libFuzzer. These are partly based on this comment bitcoin/bitcoin#17657 (comment) and discussions in the review club for #17860. See: https://bitcoincore.reviews/17860.html Based on the doc in the current state I could not compile fuzzers for AFL or libFuzzer. Using these hints, I can - compile and run fuzzers with AFL - compile but **not** run fuzzers with libFuzzer Fuzzers compiled with libFuzzers may be running but don't produce any output. Looking for others to test this to see if it is an issue with my local system. Especially interesting if you have been running libFuzzer fuzzers successfully on macOS before. Edit: Closes #17914 ACKs for top commit: MarcoFalke: ACK b6c3e84 Sjors: ACK b6c3e84 fanquake: ACK b6c3e84 - I think this has been nitpicked enough, and importantly the commands look better now. Tree-SHA512: fdbacbcf10e9353a4ac3d22edf88663e33185ad2f244b986ff74c513de05f9fa62c4d8b17985d2f9288834c124b352cf52280627b5ff095735b411b12482e2ec
2 parents 01fc589 + b6c3e84 commit 3b5b276

File tree

1 file changed

+58
-17
lines changed

1 file changed

+58
-17
lines changed

doc/fuzzing.md

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ describe how to use it with AFL and libFuzzer.
77

88
## Preparing fuzzing
99

10-
AFL needs an input directory with examples, and an output directory where it
11-
will place examples that it found. These can be anywhere in the file system,
12-
we'll define environment variables to make it easy to reference them.
13-
14-
libFuzzer will use the input directory as output directory.
10+
The fuzzer needs some inputs to work on, but the inputs or seeds can be used
11+
interchangeably between libFuzzer and AFL.
1512

1613
Extract the example seeds (or other starting inputs) into the inputs
1714
directory before starting fuzzing.
@@ -21,13 +18,19 @@ git clone https://github.com/bitcoin-core/qa-assets
2118
export DIR_FUZZ_IN=$PWD/qa-assets/fuzz_seed_corpus
2219
```
2320

24-
Only for AFL:
21+
AFL needs an input directory with examples, and an output directory where it
22+
will place examples that it found. These can be anywhere in the file system,
23+
we'll define environment variables to make it easy to reference them.
24+
25+
So, only for AFL you need to configure the outputs path:
2526

2627
```
2728
mkdir outputs
2829
export AFLOUT=$PWD/outputs
2930
```
3031

32+
libFuzzer will use the input directory as output directory.
33+
3134
## AFL
3235

3336
### Building AFL
@@ -41,16 +44,25 @@ make
4144
export AFLPATH=$PWD
4245
```
4346

47+
For macOS you may need to ignore x86 compilation checks when running `make`:
48+
`AFL_NO_X86=1 make`.
49+
4450
### Instrumentation
4551

4652
To build Bitcoin Core using AFL instrumentation (this assumes that the
4753
`AFLPATH` was set as above):
4854
```
4955
./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-gcc CXX=${AFLPATH}/afl-g++
5056
export AFL_HARDEN=1
51-
cd src/
5257
make
5358
```
59+
60+
If you are using clang you will need to substitute `afl-gcc` with `afl-clang`
61+
and `afl-g++` with `afl-clang++`, so the first line above becomes:
62+
```
63+
./configure --disable-ccache --disable-shared --enable-tests --enable-fuzz CC=${AFLPATH}/afl-clang CXX=${AFLPATH}/afl-clang++
64+
```
65+
5466
We disable ccache because we don't want to pollute the ccache with instrumented
5567
objects, and similarly don't want to use non-instrumented cached objects linked
5668
in.
@@ -60,25 +72,32 @@ The fuzzing can be sped up significantly (~200x) by using `afl-clang-fast` and
6072
compiling using `afl-clang-fast`/`afl-clang-fast++` the resulting
6173
binary will be instrumented in such a way that the AFL
6274
features "persistent mode" and "deferred forkserver" can be used. See
63-
https://github.com/mcarpenter/afl/tree/master/llvm_mode for details.
75+
https://github.com/google/AFL/tree/master/llvm_mode for details.
6476

6577
### Fuzzing
6678

6779
To start the actual fuzzing use:
6880

6981
```
70-
export FUZZ_TARGET=fuzz_target_foo # Pick a fuzz_target
82+
export FUZZ_TARGET=bech32 # Pick a fuzz_target
7183
mkdir ${AFLOUT}/${FUZZ_TARGET}
72-
$AFLPATH/afl-fuzz -i ${DIR_FUZZ_IN}/${FUZZ_TARGET} -o ${AFLOUT}/${FUZZ_TARGET} -m52 -- test/fuzz/${FUZZ_TARGET}
84+
$AFLPATH/afl-fuzz -i ${DIR_FUZZ_IN}/${FUZZ_TARGET} -o ${AFLOUT}/${FUZZ_TARGET} -m52 -- src/test/fuzz/${FUZZ_TARGET}
7385
```
7486

7587
You may have to change a few kernel parameters to test optimally - `afl-fuzz`
7688
will print an error and suggestion if so.
7789

90+
On macOS you may need to set `AFL_NO_FORKSRV=1` to get the target to run.
91+
```
92+
export FUZZ_TARGET=bech32 # Pick a fuzz_target
93+
mkdir ${AFLOUT}/${FUZZ_TARGET}
94+
AFL_NO_FORKSRV=1 $AFLPATH/afl-fuzz -i ${DIR_FUZZ_IN}/${FUZZ_TARGET} -o ${AFLOUT}/${FUZZ_TARGET} -m52 -- src/test/fuzz/${FUZZ_TARGET}
95+
```
96+
7897
## libFuzzer
7998

80-
A recent version of `clang`, the address/undefined sanitizers (ASan/UBSan) and libFuzzer is needed (all
81-
found in the `compiler-rt` runtime libraries package).
99+
A recent version of `clang`, the address/undefined sanitizers (ASan/UBSan) and
100+
libFuzzer is needed (all found in the `compiler-rt` runtime libraries package).
82101

83102
To build all fuzz targets with libFuzzer, run
84103

@@ -87,11 +106,33 @@ To build all fuzz targets with libFuzzer, run
87106
make
88107
```
89108

90-
The fuzzer needs some inputs to work on, but the inputs or seeds can be used
91-
interchangeably between libFuzzer and AFL.
92-
93109
See https://llvm.org/docs/LibFuzzer.html#running on how to run the libFuzzer
94110
instrumented executable.
95111

96-
Alternatively run the script in `./test/fuzz/test_runner.py` and provide it
97-
with the `${DIR_FUZZ_IN}` created earlier.
112+
Alternatively, you can run the script through the fuzzing test harness (only
113+
libFuzzer supported so far). You need to pass it the inputs directory and
114+
the specific test target you want to run.
115+
116+
```
117+
./test/fuzz/test_runner.py ${DIR_FUZZ_IN} bech32
118+
```
119+
120+
### macOS hints for libFuzzer
121+
122+
The default clang/llvm version supplied by Apple on macOS does not include
123+
fuzzing libraries, so macOS users will need to install a full version, for
124+
example using `brew install llvm`.
125+
126+
Should you run into problems with the address sanitizer, it is possible you
127+
may need to run `./configure` with `--disable-asm` to avoid errors
128+
with certain assembly code from Bitcoin Core's code. See [developer notes on sanitizers](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#sanitizers)
129+
for more information.
130+
131+
You may also need to take care of giving the correct path for clang and
132+
clang++, like `CC=/path/to/clang CXX=/path/to/clang++` if the non-systems
133+
clang does not come first in your path.
134+
135+
Full configure that was tested on macOS Catalina with `brew` installed `llvm`:
136+
```
137+
./configure --disable-ccache --enable-fuzz --with-sanitizers=fuzzer,address,undefined CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++ --disable-asm
138+
```

0 commit comments

Comments
 (0)