c5305fea5b | ||
---|---|---|
.. | ||
blob_to_kzg_commitment | ||
compute_blob_kzg_proof | ||
compute_kzg_proof | ||
gen_corpus | ||
verify_blob_kzg_proof | ||
verify_blob_kzg_proof_batch | ||
verify_kzg_proof | ||
.gitignore | ||
Makefile | ||
README.md | ||
base_fuzz.h |
README.md
Fuzzing
This directory contains coverage-guided fuzzers for KZG functions. It uses
LLVM's libFuzzer for the heavy lifting.
Each directory is named after a target and contains a single file (fuzz.c
)
that implements a LLVMFuzzerTestOneInput
function. These are relatively
simple; if the input matches the size requirements, it passes the data to the
target function. There is a Makefile that compiles and starts the fuzzer, which
means it should be pretty easy.
Dependencies
This is expected to run on Linux/macOS, it is not expected to work on Windows.
In addition to build-essentials
and clang
, this requires llvm
to be
installed:
Linux
sudo apt install llvm
macOS
brew install llvm
Targets
Currently, only the public KZG interface functions are fuzzable:
$ make
Available targets:
- fuzz_blob_to_kzg_commitment
- fuzz_compute_blob_kzg_proof
- fuzz_compute_kzg_proof
- fuzz_verify_blob_kzg_proof
- fuzz_verify_blob_kzg_proof_batch
- fuzz_verify_kzg_proof
To run a fuzzer, run make fuzz_<func>
like:
$ make fuzz_verify_kzg_proof
[+] Building blst
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./src/server.c
+ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./build/assembly.S
+ ar rc libblst.a assembly.o server.o
[+] Generating corpus
[+] Compiling verify_kzg_proof fuzzer
[+] Starting verify_kzg_proof fuzzer
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 855755358
INFO: Loaded 1 modules (228 inline 8-bit counters): 228 [0x1025a00f8, 0x1025a01dc),
INFO: Loaded 1 PC tables (228 PCs): 228 [0x1025a01e0,0x1025a1020),
INFO: 1 files found in ./verify_kzg_proof/corpus
INFO: seed corpus: files: 1 min: 160b max: 160b total: 160b rss: 28Mb
#2 pulse ft: 17 exec/s: 1 rss: 29Mb
#2 INITED cov: 17 ft: 17 corp: 1/160b exec/s: 1 rss: 29Mb
#4 pulse cov: 17 ft: 17 corp: 1/160b lim: 160 exec/s: 2 rss: 29Mb
#5 NEW cov: 19 ft: 20 corp: 2/320b lim: 160 exec/s: 2 rss: 29Mb L: 160/160 MS: 3 ChangeASCIIInt-ChangeBit-ChangeBit-
#7 NEW cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 3 rss: 29Mb L: 157/160 MS: 2 ChangeByte-EraseBytes-
#8 pulse cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 4 rss: 29Mb
#13 NEW cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 6 rss: 29Mb L: 160/160 MS: 1 ChangeBit-
#16 pulse cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 8 rss: 29Mb
...
There are a few steps:
- Build the blst library.
- Generate initial corpora files.
- Compile the fuzzer.
- Start the fuzzer.
Reference this page for a guide on reading the output.
To stop the fuzzer, press ctrl-C on your keyboard. It will print something like:
...
#65536 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 16384 rss: 29Mb
#131072 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 18724 rss: 29Mb
^C==11616== libFuzzer: run interrupted; exiting
make: [run_fuzz_verify_kzg_proof] Error 72 (ignored)
If your system has multiple cores, it's easy to run fuzzers on multiple threads.
Append THREADS=<n>
where n
is the number of threads you would like there to
be. If you wish to use all available CPU cores, specify -1
as the count.
$ make fuzz_verify_kzg_proof THREADS=4
[+] Starting verify_kzg_proof fuzzer
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-0.log 2>&1
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-2.log 2>&1
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-1.log 2>&1
./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-3.log 2>&1
When you press ctrl-C it will stop all the fuzzers and print their output to your console sequentially. You will most likely need to scroll up to see their outputs.
When operating in parallel (threads) the fuzzers use a shared corpus and are intelligent enough to learn from other threads that have progressed further. When you see a line that starts with "RELOAD" that fuzzer process is updating its corpus with findings from other threads.
Findings
If there is a crash or timeout, the fuzzer will write a file to the target directory containing the input data associated with that crash/timeout. If this happens, please report the finding via an issue on GitHub.