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

Reproducing fuzzer findings

OSS-Fuzz reports identify the target binary, fuzzing engine, sanitizer, and platform that found a failure. Reproduce with the closest available configuration: a crash found under UndefinedBehaviorSanitizer, for example, may not be visible in the default AddressSanitizer build.

These instructions assume that the testcase has been downloaded from the OSS-Fuzz report.

Inspect the testcase

Structured protobuf targets

The hosted corpus decoder decodes protobuf Scenario files entirely in the browser without uploading them.

From a source checkout, read_proto_corpus uses the full authoring schema to print field names. Current generated profile roots preserve its retained field numbers and wire types, so the authoring view can inspect target payloads even though libprotobuf-mutator uses a restricted target-specific type. The command can also use the metadata-free staged copy under build/schemas/ when the source schema is unavailable:

read_proto_corpus \
  clusterfuzz-testcase-minimized-curl_fuzzer_proto_http-<id>

The command requires protoc. If it cannot find either schema, it falls back to protoc --decode_raw; pass --proto-file to select one explicitly.

The typed-option cutover changed schemas/curl_fuzzer.proto in place. Always pair a structured testcase with the curl-fuzzer revision and target that produced it. A pre-cutover generic-option input can parse without error under the current schema but mean something different; the runtime deliberately does not auto-detect or fall back to the old format. Reproduce such an input at the original revision and with the target that produced it.

Published reproduction images also include the metadata-free staged authoring schema and a decode-scenario command:

docker run --rm -i \
  -v "$PWD/clusterfuzz-testcase-minimized-curl_fuzzer_proto_multi-<id>:/testcase:ro" \
  curlfuzzer.azurecr.io/address-libfuzzer \
  decode-scenario /testcase

It also accepts the testcase on standard input:

docker run --rm -i curlfuzzer.azurecr.io/address-libfuzzer decode-scenario \
  < clusterfuzz-testcase-minimized-curl_fuzzer_proto_multi-<id>

Direct parser targets consume target-specific raw bytes and generally have no separate decoder.

Reproduce with a local standalone build

Build the target, optionally against a local curl checkout:

./mainline.sh -t curl_fuzzer_proto_http
./mainline.sh -c /path/to/curl -t curl_fuzzer_proto_http

The resulting binary is under build/. Set FUZZ_VERBOSE to enable detailed libcurl logging:

FUZZ_VERBOSE=1 ./build/curl_fuzzer_proto_http \
  clusterfuzz-testcase-minimized-curl_fuzzer_proto_http-<id>

The default build uses AddressSanitizer. It is suitable for many libfuzzer_asan findings and provides a fast edit-build-replay loop. A matching OSS-Fuzz container is preferable when the report uses another sanitizer, engine, architecture, or dependency configuration.

Reproduce in OSS-Fuzz

Follow the upstream OSS-Fuzz reproduction guide for complete instructions. From an OSS-Fuzz checkout, an UndefinedBehaviorSanitizer HTTP reproduction is:

python3 infra/helper.py build_image curl
python3 infra/helper.py build_fuzzers --sanitizer undefined curl
python3 infra/helper.py reproduce \
  curl curl_fuzzer_proto_http \
  /path/to/clusterfuzz-testcase-minimized-curl_fuzzer_proto_http-<id>

Once reproduced, use the normal sanitizer stack trace, debugger, and targeted logging to narrow the fault. For AddressSanitizer investigations in GDB, a breakpoint on __asan::ReportGenericError can stop at the point where the runtime reports the invalid access.