Fixes #21461
This supports whole directory runs of the fuzzing seeds without needing a fuzzing library. A few design decisions that I went with but happy to change:
- Very basic multi arg support
a. Can have 0 args and continue to feed via file input like before
b. Can have 1 or more args that is a file or directory
d. Subdirectories are ignored if you pass in a directory (though you can use
dir/*to include files from subdirectories) - Based the file reading off of util/readwritefile.cpp with small changes to make it a buffer instead of a string (could reuse that but turn string to buffer?)
- The new changes are ignored in the
__AFL_LOOPpath or if built withoutDPROVIDE_FUZZ_MAIN_FUNCTION
<details> <summary>Testing instructions</summary>
To build without libFuzzer, exclude the sanitizers. IE:
CC=clang CXX=clang++ ./configure BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include" --without-gui --with-zmq --enable-fuzz
That should have the CPPFLAGS of -DPROVIDE_FUZZ_MAIN_FUNCTION to indicicate it was built with the main function to use instead of the libFuzzer LLVMFuzzerInitialize & LLVMFuzzerTestOneInput methods.
Tests:
# clean and build
make clean
make -j "$(($(nproc)+1))"
# get qa-assets if you don't have already
git clone https://github.com/bitcoin-core/qa-assets
# existing way to feed 1 at a time, still supported
FUZZ=process_message src/test/fuzz/fuzz < qa-assets/fuzz_seed_corpus/process_message/1258dd51f2a5f3221b33a306279ef7290c5fca6d
# new with this PR: one at a time
FUZZ=process_message src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_message/1258dd51f2a5f3221b33a306279ef7290c5fca6d
# or multiple files at the same time
FUZZ=process_message src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_message/1258dd51f2a5f3221b33a306279ef7290c5fca6d qa-assets/fuzz_seed_corpus/process_message/32230c42df1caa3220a3f95ee8a8d2865731ca3e qa-assets/fuzz_seed_corpus/process_message/90329d105d238ed81452077b4e0287a2040db9e9
# new with this PR: whole directory at a time
FUZZ=process_message src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_message
# or mix of files and directories at the same time
FUZZ=process_message src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_message/1258dd51f2a5f3221b33a306279ef7290c5fca6d qa-assets/fuzz_seed_corpus/process_message/32230c42df1caa3220a3f95ee8a8d2865731ca3e qa-assets/fuzz_seed_corpus/process_message/90329d105d238ed81452077b4e0287a2040db9e9 qa-assets/fuzz_seed_corpus/process_message/
# new with this PR: wildcard support
FUZZ=process_messages src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_messages/*
# new with this PR: run all seeds in all targets, one target/directory at a time
for D in qa-assets/fuzz_seed_corpus/*; do [ -d "${D}" ] && echo "${D##*/}" && FUZZ="${D##*/}" src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/"${D##*/}"; done
</details>
Happy to make any changes and very much welcome code feedback, my c++ a bit rusty and still figuring out the codebase.