Files
wget2/fuzz/README.md
Tim Rühsen f7e4c13099 Add wget_options_fuzzer
* Makefile.am: Fix make target 'fuzz-coverage'
* configure.ac: Enable building static library by default,
  add option --enable-fuzzing
* fuzz/Makefile.am: Add wget_options_fuzzer,
  check for FUZZING (set with --enable-fuzzing)
* fuzz/README.md: Amend the text
* fuzz/main.c: Use printf() instead of wget_info_printf()
* fuzz/run-clang.sh: Use fuzzer binaries built by 'make'
* fuzz/wget_options_fuzzer.c: New fuzzer
* fuzz/wget_options_fuzzer.dict: New fuzzer dictionary
* fuzz/wget_options_fuzzer.in/*: Initial fuzz corpora
* libwget/net.c: Skip IP address resolution when fuzzing
* src/log.c: Don't create files when fuzzing,
  don't print to console when fuzzing
* src/options.c: Add set_exit_status() and get_exit_status(),
  don't print --help / --version to console when fuzzing,
  do not call exit() - return error instead,
  fix recursion level in _read_config(),
  don't create files when fuzzing,
  fix memory leaks in deinit()
* src/stats.c: Don't create files when fuzzing
* src/wget.c: Remove set_exit_status()
* src/wget_main.h: Remove exit_status_t
* src/wget_options.h: Add exit_status_t
* tests/test-plugin.c: Fix expected exit codes from 1 to 2

This is for application fuzzing (namely code from src/).
The code in src/ had to be prepared in certain ways, but it
doesn't add significant overhead, even makes the code cleaner
in some ways. Several of these changes have already been committed
into the master branch.
2017-10-26 15:41:01 +02:00

2.7 KiB

Fuzzers

These are fuzzers designed for use with libFuzzer or afl. They can be used to run on Google's OSS-Fuzz (https://github.com/google/oss-fuzz/).

The convention used here is that the initial values for each parser fuzzer are taken from the $NAME.in directory.

Crash reproducers from OSS-Fuzz are put into $NAME.repro directory for regression testing with top dir 'make check' or 'make check-valgrind'.

Running a fuzzer using clang

Use the following commands on top dir:

export CC=clang-6.0
export CFLAGS="-O1 -g -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined,integer,nullability -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp"
export LIB_FUZZING_ENGINE="-lFuzzer -lstdc++"
./configure --enable-fuzzing --disable-doc --disable-manywarnings
make clean
make -j$(nproc)
cd fuzz

# run libwget_xml_parse_buffer_fuzzer
UBSAN_OPTIONS=print_stacktrace=1 ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer \
  ./run-clang.sh libwget_xml_parse_buffer_fuzzer

If you see a crash, then a crash corpora is written that can be used for further investigation. E.g.

==2410==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000004e90 at pc 0x00000049cf9c bp 0x7fffb5543f70 sp 0x7fffb5543720
...
Test unit written to ./crash-adc83b19e793491b1c6ea0fd8b46cd9f32e592fc

To reproduce the crash:

./libwget_xml_parse_buffer_fuzzer < ./crash-adc83b19e793491b1c6ea0fd8b46cd9f32e592fc

You can also copy/move that file into libwget_xml_parse_buffer_fuzzer.repro/ and re-build the project without fuzzing for a valgrind run, if you like that better. Just a ./configure (maybe with sanitizers enabled) and a make check-valgrind should reproduce it.

Running a fuzzer using AFL

Use the following commands on top dir:

$ CC=afl-clang-fast ./configure --disable-doc
$ make -j$(nproc) clean all
$ cd fuzz
$ ./run-afl.sh libwget_xml_parse_buffer_fuzzer

Fuzz code coverage using the corpus directories *.in/

Code coverage reports currently work best with gcc+lcov+genhtml.

In the top directory:

CC=gcc CFLAGS="-O0 -g" ./configure --disable-doc --disable-manywarnings
make fuzz-coverage
xdg-open lcov/index.html

Each fuzzer target has it's own files/functions to cover, e.g. libwget_xml_parse_buffer covers libwget/xml.c (except wget_xml_parse_file() and wget_html_parse_file()).

To work on corpora for better coverage, cd fuzz and use e.g. ./view-coverage.sh libwget_xml_parse_buffer_fuzzer.

Creating wget_options_fuzzer.dict

for i in `../src/wget2 --help|tr ' ' '\n'|grep ^--|cut -c 3-|sort`;do echo \"$i\"; done >wget_options_fuzzer.dict