# alktty fuzzing cargo-fuzz targets for the wire-facing parse surfaces. The design and operating rules live in `docs/plans/fuzzing.md` (adopted from alkcall's `docs/research/fuzzing.md`); this README is the operational cheat-sheet. ## Layout - `fuzz_targets/` — nightly-only `fuzz_target!` binaries (thin wrappers). - `shared/` — stable-toolchain library holding the invariant logic; the corpus replay tests run here on plain `cargo test`. - `corpus//` — committed seeds (regenerate with `python3 fuzz/gen_fuzz_seeds.py`). - `artifacts/` — gitignored crash/oom/timeout artifacts + campaign logs. ## Targets | Target | Drives | |---|---| | `chunk_frame` | `ChunkReader`/`ChunkWriter` (5-byte chunk codec, ADR-001) | | `negotiation_frame` | `NegotiationReader`/`NegotiationWriter` + `NegotiateRequest` + `error_response_bytes` + the cross-codec peek-disambiguation seam | | `control_json` | `ControlMessage::from_slice`/`to_json` + `signal_from_name` | | `session_opseq` | the producer session pump (`drive_session_pre_negotiated`) + a fuzz-local mock backend — the stateful op-sequence target (ADR-004/ADR-005 invariants; the alkcall-bug-class hunt) | ## Running a campaign — always detached Agent sessions must never run fuzzing in the foreground (an OOM in a target can take down the session host; see docs/plans/fuzzing.md §3). Use the detached runner: ```bash fuzz/run-detached.sh chunk_frame # poll: tail -n 50 fuzz/artifacts/chunk_frame-*.log ls fuzz/artifacts/chunk_frame/ pgrep -f "cargo fuzz run chunk_frame" ``` `FUZZ_RUNTIME_SECS=1800 fuzz/run-detached.sh negotiation_frame` for a longer campaign. The runner pins `-fork=1 -rss_limit_mb=2048 -malloc_limit_mb=2048 -timeout=25` and detaches via `setsid` + `nohup`. ## Corpus replay (the standing fuzz gate) ```bash cargo test --manifest-path fuzz/shared/Cargo.toml ``` Replays every committed seed through the same invariant functions the fuzzer runs, on stable, no nightly needed. Part of the release verification checklist (AGENTS.md). ## Toolchain notes `rust-toolchain.toml` pins nightly for this subtree only (llvm-tools required by cargo-fuzz); the crate itself stays on stable at MSRV 1.88. `cargo fuzz build` must be run with the fuzz dir as CWD or trust the toolchain file (rustup resolves per directory). Run campaigns before releases and after touching `src/wire.rs`, `src/negotiation.rs`, `src/control.rs`, the adapter, or the session pump. ## session_opseq notes The op-sequence target is inherently slower than the byte-format targets (each input drives a full tokio session with bounded reads and yields — tens of exec/s per worker, not millions). That is expected: the value is state-space exploration, not throughput. It uses `tokio::time::timeout` internally, so the nightly target needs the `--features time` tokio surface already present via the shared crate's deps — no extra flags. Its invariants (kill-on-Drop, exit-chunk-is-last, sentinel/FIFO semantics) are the ones unit tests assert individually; the fuzzer explores interleavings no example test can enumerate.