c-kzg-4844/fuzz/README.md

4.4 KiB

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.