Extending the legacy fuzzers
Legacy inputs are a persistent binary format. Treat an assigned type number as
part of the corpus compatibility contract: allocate a previously unused ID and
never reuse or renumber an existing one. The grouped ranges in
legacy_tlv_mutator.cc also make the value representation part of that choice.
Add a TLV type
- Add the
TLV_TYPE_*value tocurl_fuzzer.h. - Implement its behavior in
fuzz_parse_tlv()incurl_fuzzer_tlv.cc.FSINGLETONTLVhandles a string-valued curl option,FU32TLVhandles a four-byte option declared by libcurl aslong, andFU32TLV_OFF_Thandles a four-byte option declared ascurl_off_t. The numeric macros enforce these option families at compile time. List-like, raw-byte, or nested data needs an explicit switch case and cleanup inFUZZ_DATAwhere applicable. - Add the same numeric ID to
BaseTypeand a decoder label toTYPEMAPinsrc/curl_fuzzer_tools/corpus.py. If contributors should be able to seed it from the command line, add the corresponding argument and encoder call insrc/curl_fuzzer_tools/generate_corpus.py. - Audit
GetTypeInfo()and the type-selection bounds inlegacy_tlv_mutator.cc. The mutator must know whether the payload is bytes, a string, a four-byte integer, or nested MIME, and whether it may repeat. Extending an ID range can also require updating the maximum known ID, the dense ordinal mapping, and its compile-time synchronization assertions. - If the option can trigger name resolution or another external side effect, extend the mutator’s canonicalization/safety policy and its tests before making that type eligible for structured insertion.
- Add focused parser, generator, and mutator tests, then generate or update a seed that reaches the new behavior.
FUZZ_CURLOPT_TRACKER_SPACE is not a TLV-ID limit. FSET_OPTION and
FCHECK_OPTION_UNSET index the tracker with CURLOPTNAME % 1000; when adding a
tracked curl option, verify that this remainder is smaller than the allocated
tracker space. The tracker enforces singleton curl options; this size check
avoids introducing an out-of-bounds index.
tests/test_tlv_constants_sync.py rejects duplicate numeric IDs and missing or
extra values between curl_fuzzer.h and Python’s BaseType. It does not
replace the behavioral tests needed for the parser and mutator.
Add a protocol target
When a new target can use the existing TLV execution model:
- Add
fuzzer_entrypoints/<target>.ccfollowing an existing legacy wrapper. Its basename must match the executable so coverage and Fuzz Introspector attribution remain distinct. - Add
curl_add_fuzzer(<target> <TOKEN>)and the target to the aggregatefuzztarget inCMakeLists.txt. This definesFUZZ_PROTOCOLS_<TOKEN>for the shared sources. - Add or reuse the matching branch in
fuzz_set_allowed_protocols()inlegacy_fuzzer.cc. If this expands the generic target too, update the reviewed list inlegacy_protocol_allowlist.cc. Protocols that can bypass the fake-socket model require a safety review rather than automatic inclusion. - Teach
DefaultUrl(),DefaultResponse(), and, where appropriate,TargetNeedsResponse()inlegacy_tlv_mutator.cchow to create useful transfer scaffolding for the compile-time token. - Add the executable to
scripts/fuzz_targetsso packaging, public-corpus downloads, and replay tooling agree with CMake. - Create
corpora/<target>/with at least one decoded and replayed seed.
The generic allow-list deliberately excludes protocols such as TELNET when the legacy harness cannot safely isolate their I/O. A new protocol-specific target must preserve the harness’s isolation and must not introduce an unintended network or blocking-standard-input path.
Relevant checks
Run the focused Python checks after changing IDs, generation, entrypoints, or packaging:
python -m pip install -e '.[python-tests]'
python -m pytest \
tests/test_tlv_constants_sync.py \
tests/test_generate_corpus.py \
tests/test_fuzzer_entrypoints.py
After configuring a normal build, compile and run the C++ policy tests:
cmake --build build --target \
legacy_tlv_mutator_test legacy_protocol_allowlist_test
ctest --test-dir build --output-on-failure \
-R 'legacy_(tlv_mutator|protocol_allowlist)_test'
tests/legacy_tlv_mutator_test.cc covers framing, bounds, transfer-scaffold
repair, routing canonicalization, raw mutation, and record crossover.
tests/legacy_protocol_allowlist_test.cc verifies that the generic allow-list
is both supported by the linked libcurl and limited to reviewed protocols. A
full AddressSanitizer ./mainline.sh build also builds fuzzer_unit_tests and
runs CTest.