Files
alksocks/fuzz
glm-5.3-flash 08a3694464 fuzz: adopt fuzzing (wave 1) + alkcall 0.8.1 / alktunnels 0.2.1 bumps
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)
2026-09-28 11:18:08 +00:00
..

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; thin fuzz_target! wrappers.
  • shared/ — the invariant logic, as a plain library so normal cargo 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 with python3 fuzz/gen_fuzz_seeds.py from the repo root). Grown corpora and artifacts are gitignored.
  • run-detached.sh — mandatory runner for agent sessions: wraps cargo fuzz run in setsid + 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.