Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Working with legacy corpora

Checked-in seeds live in corpora/<target>/. The active target list is maintained in scripts/fuzz_targets; do not infer it from old corpus directories that may remain for historical targets.

The commands below assume the repository’s Python package is installed in an active Python 3.10 or newer environment:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .

With uv, the same tools can be invoked as uv run read_corpus, uv run generate_corpus, and uv run generate_decoder_html without manually activating the environment.

Inspect a testcase

read_corpus prints one decoded record per line:

$ read_corpus corpora/curl_fuzzer_http/test_url_http
TLVContents(type='CURLOPT_URL' (1), length=16, data=b'http://127.0.0.1')

For interactive inspection, use the published corpus decoder. It recognizes legacy TLV inputs and reads the selected file entirely in the browser. To generate a standalone copy locally:

generate_decoder_html --output /tmp/curl-corpus-decoder.html

Generate a seed

generate_corpus always requires an output path and URL. Other flags add responses, uploads, authentication, headers, MIME parts, and selected curl options. Run generate_corpus --help for the implemented set.

The historical --hsts argument emits disabled TLV type 51 and should not be used for a new seed; see Parser behavior.

This Bash example creates an HTTP seed with an initial server response and then checks its contents:

generate_corpus \
  --output /tmp/http-seed \
  --url http://127.0.0.1/ \
  --rsp0 $'HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n'
read_corpus /tmp/http-seed

Responses can instead come from a binary file (--rsp0file) or the <reply><data> section of a curl test (--rsp0test together with --curl_test_dir). Repeated options such as --header, --mailrecipient, and --mimepart name:value may be supplied more than once.

Before checking in a seed, put it under the matching active target directory, decode it, and replay it with that target. A protocol-specific URL is important: an HTTP-only executable will reject an FTP URL before reaching FTP code.

Build and replay

Build one target with the repository’s standalone replay engine:

./mainline.sh -t curl_fuzzer_http

The resulting runner accepts files and directories. A directory is walked recursively:

./build/curl_fuzzer_http corpora/curl_fuzzer_http/test_url_http
./build/curl_fuzzer_http corpora/curl_fuzzer_http/

Set FUZZ_VERBOSE=1 when replaying one testcase to show curl’s verbose trace and the simulated peer traffic:

FUZZ_VERBOSE=1 ./build/curl_fuzzer_http /path/to/testcase

The default local build replays inputs; it does not perform mutation. Follow the local mutation workflow to build and run the target through OSS-Fuzz’s libFuzzer environment. LibFuzzer then discovers LLVMFuzzerCustomMutator and LLVMFuzzerCustomCrossOver from legacy_tlv_mutator.cc; see Legacy TLV fuzzers for their policy.

Public OSS-Fuzz corpora

Download all currently published corpora with:

./scripts/download_public_corpus.sh

The script writes each archive beneath ossfuzz_corpus/<target>/, skips targets without a published archive, and accepts -f to refresh existing downloads. codecoverage.sh replays these directories alongside the checked-in seeds when they are present.