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.