Skip to content

Commit b6c3e84

Browse files
committed
doc: Improve fuzzing docs for macOS users
1 parent e7f8450 commit b6c3e84

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)