1# Fuzzing 2 3Each fuzzing target can be built with multiple engines. 4Zstd provides a fuzz corpus for each target that can be downloaded with 5the command: 6 7``` 8make corpora 9``` 10 11It will download each corpus into `./corpora/TARGET`. 12 13## fuzz.py 14 15`fuzz.py` is a helper script for building and running fuzzers. 16Run `./fuzz.py -h` for the commands and run `./fuzz.py COMMAND -h` for 17command specific help. 18 19### Generating Data 20 21`fuzz.py` provides a utility to generate seed data for each fuzzer. 22 23``` 24make -C ../tests decodecorpus 25./fuzz.py gen TARGET 26``` 27 28By default it outputs 100 samples, each at most 8KB into `corpora/TARGET-seed`, 29but that can be configured with the `--number`, `--max-size-log` and `--seed` 30flags. 31 32### Build 33It respects the usual build environment variables `CC`, `CFLAGS`, etc. 34The environment variables can be overridden with the corresponding flags 35`--cc`, `--cflags`, etc. 36The specific fuzzing engine is selected with `LIB_FUZZING_ENGINE` or 37`--lib-fuzzing-engine`, the default is `libregression.a`. 38Alternatively, you can use Clang's built in fuzzing engine with 39`--enable-fuzzer`. 40It has flags that can easily set up sanitizers `--enable-{a,ub,m}san`, and 41coverage instrumentation `--enable-coverage`. 42It sets sane defaults which can be overridden with flags `--debug`, 43`--enable-ubsan-pointer-overflow`, etc. 44Run `./fuzz.py build -h` for help. 45 46### Running Fuzzers 47 48`./fuzz.py` can run `libfuzzer`, `afl`, and `regression` tests. 49See the help of the relevant command for options. 50Flags not parsed by `fuzz.py` are passed to the fuzzing engine. 51The command used to run the fuzzer is printed for debugging. 52 53## LibFuzzer 54 55``` 56# Build the fuzz targets 57./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan --cc clang --cxx clang++ 58# OR equivalently 59CC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-asan --enable-ubsan 60# Run the fuzzer 61./fuzz.py libfuzzer TARGET <libfuzzer args like -jobs=4> 62``` 63 64where `TARGET` could be `simple_decompress`, `stream_round_trip`, etc. 65 66### MSAN 67 68Fuzzing with `libFuzzer` and `MSAN` is as easy as: 69 70``` 71CC=clang CXX=clang++ ./fuzz.py build all --enable-fuzzer --enable-msan 72./fuzz.py libfuzzer TARGET <libfuzzer args> 73``` 74 75`fuzz.py` respects the environment variables / flags `MSAN_EXTRA_CPPFLAGS`, 76`MSAN_EXTRA_CFLAGS`, `MSAN_EXTRA_CXXFLAGS`, `MSAN_EXTRA_LDFLAGS` to easily pass 77the extra parameters only for MSAN. 78 79## AFL 80 81The default `LIB_FUZZING_ENGINE` is `libregression.a`, which produces a binary 82that AFL can use. 83 84``` 85# Build the fuzz targets 86CC=afl-clang CXX=afl-clang++ ./fuzz.py build all --enable-asan --enable-ubsan 87# Run the fuzzer without a memory limit because of ASAN 88./fuzz.py afl TARGET -m none 89``` 90 91## Regression Testing 92 93The regression test supports the `all` target to run all the fuzzers in one 94command. 95 96``` 97CC=clang CXX=clang++ ./fuzz.py build all --enable-asan --enable-ubsan 98./fuzz.py regression all 99CC=clang CXX=clang++ ./fuzz.py build all --enable-msan 100./fuzz.py regression all 101``` 102