Adopt the alk*/fuzzing posture (alkcall 0.8.1 + alktunnels 0.2.1 precedent) before the v0.1 publish — the cheapest moment this crate will ever have for it: - alkcall 0.8.1 + alktunnels 0.2.1: the duplicate-adopt/open fix is directly relevant to this crate's consumer open/adopt paths - fuzz/ workspace (the sibling layout): nightly-pinned subtree, stable fuzz/shared library (corpus replay = the fuzz gate), detached runner, JSON dict, deterministic seed generator; 129 committed seeds - three wave-1 targets over already-pub APIs: datagram_codec (the ASSOCIATE frame codec — the alkcall-fuzz-doc-assigned downstream target), rfc1928_codec (the forked RFC 1928 core's handshake state machines, both protocol directions), params_parse (the wire-stable open-op surface) - one diagnostic: DatagramReader::retained_bytes() (the decoder-state bound's assertion target, the alktunnels retained_bytes() posture) - docs/research/fuzzing.md: the scoped plan + implementation log; AGENTS.md gains the corpus-replay verification line - campaigns: 3 × 10-min detached runs exited 0 (datagram ~1.9M execs, rfc1928 ~2.0M, params ~3.1M; oom/timeout/crash 0/0/0 on all 33 fork jobs per target; coverage saturated on both codec targets). No crate bugs; three harness-model defects found + fixed (2 pre-campaign by corpus replay, 2 campaign-found, crash inputs promoted as seeds 900/ 901): the len==0 well-framed decode partition, the fieldless-struct serde-seq form, the BadAtyp re-frame arm, the short-domain count-walk gate - wave 2 (session_pumps stateful target) deferred to post-0.1 — the byte-level targets carry the attacker-reachable load for the publish Verification: cargo test (15 suites ok, default + all-features), clippy (all-targets + wasm + fuzz/shared), fmt, cargo doc, publish --dry-run, corpus replay 129 seeds green, cargo fuzz build clean. Refs: alkcall docs/research/fuzzing.md (§7.9 posture), alktunnels docs/research/fuzzing.md; docs/research/fuzzing.md (this crate's copy)
alksocks fuzzing
libFuzzer targets for alksocks' wire surfaces (see
docs/research/fuzzing.md for the full rationale and campaign plan).
Layout
fuzz_targets/— one binary per target; thinfuzz_target!wrappers.shared/— the invariant logic, as a plain library so normalcargo test(stable toolchain) can replay the committed corpora through the same invariants (fuzz/shared/src/*.rs#[cfg(test)]modules; quinn's CI pattern). The fuzz binaries are nightly-only; the shared crate is stable-clean.corpus/<target>/— committed hand-made seeds (regenerate withpython3 fuzz/gen_fuzz_seeds.pyfrom the repo root). Grown corpora and artifacts are gitignored.run-detached.sh— mandatory runner for agent sessions: wrapscargo fuzz runinsetsid+nohup+ log redirection so an OOM in a target can never take down the agent host (research doc §5).json.dict— JSON token dictionary for the params target.
Targets
| Target | Drives | Invariants |
|---|---|---|
datagram_codec |
DatagramReader::feed / frame / frame_inner (src/wire.rs) |
no-panic; infallible reassembly with the decode-error partition; empty-payload F-2 layering; bad-ATYP loudness; splitting transparency; round-trips; the joint bound (incl. the 65766 shape); the decoder-state retained-bytes bound |
rfc1928_codec |
the forked RFC 1928 core (src/rfc1928/): read_address, the server typestate handshake, the RFC 1929 sub-handshake, the RFC UDP header codec, ReplyError::from_u8 |
no-panic on any byte sequence, both protocol directions; typed failures only (the F-1 class); round-trips; the full-domain reply table |
params_parse |
Socks5Params / socks5_open_spec() / the reason surface (src/params.rs) |
no-panic; the trivial-params pin; the spec is a constant (the wire-stable ADR-001 surface + the schema/typed-view drift guard); the pass-through reason-extraction posture |
Commands
cargo fuzz build and cargo fuzz run must be executed with fuzz/
(or deeper) as the working directory so rustup selects the pinned
nightly toolchain — the detached runner handles that itself.
# build (nightly, pinned by rust-toolchain.toml inside fuzz/; run from fuzz/)
cargo fuzz build
# agent sessions: detached campaign (never foreground; CWD-independent)
FUZZ_RUNTIME_SECS=600 fuzz/run-detached.sh datagram_codec -max_len=65536
FUZZ_RUNTIME_SECS=600 fuzz/run-detached.sh rfc1928_codec -max_len=4096 -use_value_profile=1
FUZZ_RUNTIME_SECS=600 fuzz/run-detached.sh params_parse -dict=json.dict -use_value_profile=1
# corpus replay through the invariants (stable toolchain, no nightly)
cargo test --manifest-path fuzz/shared/Cargo.toml
# coverage
cargo fuzz coverage <target>
The fuzz workspace is excluded from the main workspace and from the
published package (exclude in the root Cargo.toml); it pins its own
nightly toolchain via rust-toolchain.toml and does not affect the
crate's stable MSRV.