zstd/tests/fuzz
Nick Terrell 09caa4d800 [fuzzer] Add a fuzzer for frame info functions
Add a fuzzer that fuzzes all helper functions that take compressed
input. This fuzzer caught one out of bounds read in
`ZSTD_decompressBound()`.
2019-04-17 11:29:42 -07:00
..
.gitignore complete ignore list 2017-12-29 14:39:49 +01:00
block_decompress.c Add block fuzzers 2017-09-13 17:44:41 -07:00
block_round_trip.c [fuzz] Speed up round trip tests 2017-09-26 14:03:43 -07:00
default.options [fuzz] Small changes for oss-fuzz integration 2017-09-27 18:23:06 -07:00
dictionary_decompress.c [fuzzer] Use ZSTD_DCtx_loadDictionary_advanced() half the time 2019-04-09 18:02:22 -07:00
dictionary_round_trip.c [fuzzer] Use ZSTD_DCtx_loadDictionary_advanced() half the time 2019-04-09 18:02:22 -07:00
fuzz_helpers.h Spelling (#1582) 2019-04-12 11:18:11 -07:00
fuzz.h grouped debug functions into debug.h 2018-06-13 15:43:09 -04:00
fuzz.py [fuzzer] Add a fuzzer for frame info functions 2019-04-17 11:29:42 -07:00
Makefile [fuzzer] Add a fuzzer for frame info functions 2019-04-17 11:29:42 -07:00
README.md Spelling (#1582) 2019-04-12 11:18:11 -07:00
regression_driver.c [fuzzer] Make the regression_driver work while fuzzers are active 2019-04-09 18:01:49 -07:00
simple_decompress.c Update fuzzer sources 2017-09-13 16:16:57 -07:00
simple_round_trip.c [fuzzer] Sometimes fuzz with one less output byte 2019-04-09 16:47:59 -07:00
stream_decompress.c [fuzz] Use the new advanced API 2019-04-08 20:01:38 -07:00
stream_round_trip.c [fuzzer] Fix stream_round_trip for the new options 2019-04-08 21:06:19 -07:00
zstd_frame_info.c [fuzzer] Add a fuzzer for frame info functions 2019-04-17 11:29:42 -07:00
zstd_helpers.c Spelling (#1582) 2019-04-12 11:18:11 -07:00
zstd_helpers.h [fuzzer] Add dictionary fuzzers 2019-04-08 21:07:28 -07:00

Fuzzing

Each fuzzing target can be built with multiple engines. Zstd provides a fuzz corpus for each target that can be downloaded with the command:

make corpora

It will download each corpus into ./corpora/TARGET.

fuzz.py

fuzz.py is a helper script for building and running fuzzers. Run ./fuzz.py -h for the commands and run ./fuzz.py COMMAND -h for command specific help.

Generating Data

fuzz.py provides a utility to generate seed data for each fuzzer.

make -C ../tests decodecorpus
./fuzz.py gen TARGET

By default it outputs 100 samples, each at most 8KB into corpora/TARGET-seed, but that can be configured with the --number, --max-size-log and --seed flags.

Build

It respects the usual build environment variables CC, CFLAGS, etc. The environment variables can be overridden with the corresponding flags --cc, --cflags, etc. The specific fuzzing engine is selected with LIB_FUZZING_ENGINE or --lib-fuzzing-engine, the default is libregression.a. It has flags that can easily set up sanitizers --enable-{a,ub,m}san, and coverage instrumentation --enable-coverage. It sets sane defaults which can be overridden with flags --debug, --enable-ubsan-pointer-overflow, etc. Run ./fuzz.py build -h for help.

Running Fuzzers

./fuzz.py can run libfuzzer, afl, and regression tests. See the help of the relevant command for options. Flags not parsed by fuzz.py are passed to the fuzzing engine. The command used to run the fuzzer is printed for debugging.

LibFuzzer

# Build libfuzzer if necessary
make libFuzzer
# Build the fuzz targets
./fuzz.py build all --enable-coverage --enable-asan --enable-ubsan --lib-fuzzing-engine Fuzzer/libFuzzer.a --cc clang --cxx clang++
# OR equivalently
CC=clang CXX=clang++ LIB_FUZZING_ENGINE=Fuzzer/libFuzzer.a ./fuzz.py build all --enable-coverage --enable-asan --enable-ubsan
# Run the fuzzer
./fuzz.py libfuzzer TARGET -max_len=8192 -jobs=4

where TARGET could be simple_decompress, stream_round_trip, etc.

MSAN

Fuzzing with libFuzzer and MSAN will require building a C++ standard library and libFuzzer with MSAN. fuzz.py respects the environment variables / flags MSAN_EXTRA_CPPFLAGS, MSAN_EXTRA_CFLAGS, MSAN_EXTRA_CXXFLAGS, MSAN_EXTRA_LDFLAGS to easily pass the extra parameters only for MSAN.

AFL

The default LIB_FUZZING_ENGINE is libregression.a, which produces a binary that AFL can use.

# Build the fuzz targets
CC=afl-clang CXX=afl-clang++ ./fuzz.py build all --enable-asan --enable-ubsan
# Run the fuzzer without a memory limit because of ASAN
./fuzz.py afl TARGET -m none

Regression Testing

The regression rest supports the all target to run all the fuzzers in one command.

CC=clang CXX=clang++ ./fuzz.py build all --enable-asan --enable-ubsan
./fuzz.py regression all
CC=clang CXX=clang++ ./fuzz.py build all --enable-msan
./fuzz.py regression all