# Fuzz targets Requires nightly and [`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz): ```sh cargo install cargo-fuzz ``` ## Targets | target | what it covers | | ------ | -------------- | | `read_arbitrary` | `Reader` over arbitrary bytes: never panics, never yields more items than the input has bytes, and any error is terminal | | `verify_arbitrary` | `verify_archive` over arbitrary bytes: header parse, MST reconstruction, and the LtHash fold | | `roundtrip_space` | structured: anything `encode_space_archive` accepts must verify and read back identically | | `flaky_source` | `Reader` over a source that short-reads and errors on a fuzzer-chosen schedule | ## Running The two byte-oriented targets need the seed corpus to get past the header — random bytes essentially never form a valid archive, and without seeds they only ever exercise "reject bad magic". Pass `seeds/` as a second corpus directory: ```sh cargo +nightly fuzz run read_arbitrary corpus/read_arbitrary seeds/read_arbitrary cargo +nightly fuzz run verify_arbitrary corpus/verify_arbitrary seeds/verify_arbitrary ``` The seeds are worth roughly 30x the edge coverage on `verify_arbitrary`. The structured targets generate their own valid inputs, so they need no seeds: ```sh cargo +nightly fuzz run roundtrip_space cargo +nightly fuzz run flaky_source ``` ## Why `flaky_source` exists The other targets read from a slice, which only ever succeeds or hits clean EOF. Real sources — sockets, pipes, failing disks — return `Interrupted`, short reads, and persistent errors, and a reader is most likely to spin or lose its place on exactly those paths. This is not hypothetical: the reader once had a bug where an error left the iterator un-finished, so `for entry in reader` looped forever. It was *not* reachable from a truncated byte slice (the next read hits clean EOF and ends the iteration) — only from a source that keeps erroring. A slice-based fuzzer would never have found it. `seeds/` is checked in; `corpus/` and `artifacts/` are generated and ignored.