fuzz-target-every-parse: the §3.2 differential target — three parsers + skip_forward through the doc-hidden surfaces via shared invariants, 66 committed seeds + gitignore negation + README row; two real skip_forward findings fixed inline (division-by-zero/negative-interval wrap on sqlite+mem, i64 gap subtraction overflow on all three engines incl. pg) and registered as PROVENANCE D-38

This commit is contained in:
glm-5.3-flash committed 2026-10-10 22:01:13 +00:00
1 parent 1f6cc0970a
commit f7c1bd79b0
80 files changed
+1559 -18

No files matched your search

+113 -9
View File
@@ -1,7 +1,7 @@
---
id: fuzz-target-every-parse
name: Fuzz target — `every_parse` (the three `@every` parsers, differential)
status: pending
status: completed
depends_on: [fuzz-scaffold, fuzz-parser-exposure]
scope: moderate
risk: medium
@@ -73,17 +73,23 @@ escalate), not a task failure.
## Acceptance Criteria
- [ ] `fuzz_targets/every_parse.rs` + `shared/src/every_parse.rs`
- [x] `fuzz_targets/every_parse.rs` + `shared/src/every_parse.rs`
exist; `cargo fuzz build` builds the target
- [ ] All five §3.2 invariant classes implemented and exercised by both
- [x] All five §3.2 invariant classes implemented and exercised by both
the fuzz path and the replay module; the three-way agreement
asserted on every input (fuzz) and every seed (replay)
- [ ] Seed corpus committed, deterministic-generated, gitignore
- [x] Seed corpus committed, deterministic-generated, gitignore
negation in place
- [ ] `cargo test --manifest-path fuzz/shared/Cargo.toml` green;
- [x] `cargo test --manifest-path fuzz/shared/Cargo.toml` green;
`shared` clippy/fmt gates green
- [ ] Root workspace gates still green; substrate diff still empty
- [ ] Any three-way divergence found during target development is
- [x] Root workspace gates still green; substrate diff still empty
*(amended at implementation, 2026-10-10 — see Notes: the target
found a real no-panic/overflow-posture finding in `skip_forward`,
dispositioned inline per the task's own finding posture; the
substrate delta is two keyword-free lines in the re-derived
`queue_ops.rs`, registered as PROVENANCE D-38; lineage body
untouched)*
- [x] Any three-way divergence found during target development is
recorded in Notes with its disposition (fixed / escalated), not
silently absorbed
@@ -101,8 +107,106 @@ escalate), not a task failure.
## Notes
> To be filled by implementation agent
Decisions of record the implementation made that the description didn't
pin:
- **Two real findings, both in `skip_forward` (the boundary leg),
dispositioned fixed inline** (per this task's risk note, the
campaign task's posture — small crate-side fixes ride the task that
finds them):
1. **Division-by-zero panic + negative-`interval` under-wrap** —
SQLite and mem's `skip_forward` cast `interval` straight into
`i128` (pg had `interval.max(1)`); `interval == 0` panicked on
i128 division, and a negative `interval` skipped the high-side
guard so `next < i64::MIN` wrapped silently. Fix: the clamp, pg's
committed shape. With `interval >= 1` the under-flow path is
unreachable, so the fix is exactly pg's body — no extra guard was
added beyond it.
2. **i64 gap subtraction before the i128 cast (all three engines,
including pg)** — `(now - next_fire_at) as i128` computed the
difference in i64: panics (debug overflow) / wraps silently
(release) when `(next_fire_at, now)` straddle the full domain
(`now = i64::MIN`-adjacent, `next_fire_at = i64::MAX`-adjacent).
The 128-bit intermediates story had a hole at its first line. Fix:
`now as i128 - next_fire_at as i128` — same one line, all three.
Observable reachability: both pre-fix paths are reachable only
outside the parsers' grammar domain (`n <= 0` rejected ⇒ callers
pass `interval >= 1`; `|gap| < i64` range in every clock-domain
call) — no engine-internal behavior change; the invariant now holds
over the whole domain. SQLite's delta registered as
`substrate/PROVENANCE.md` **D-38** (queue_ops.rs is the re-derived
half, D-12's own — D-31/D-37's precedent for owned-code deltas in
the register); mem needs no provenance entry (engine-owned
`scheduler.rs`), and pg's one-line delta is engine-owned likewise.
- **(a)-companion leg not built.** The optional `schedule()`-driven
register-posture leg stayed unbuilt: the register-path posture (parse
→ first-boundary `checked_add` → reject `InvalidSpec`) is suite-pinned
already, and driving the mem factory from `shared` would pull a
tokio runtime into the stable gate crate for one redundant leg.
- **`skip_forward` three-way equality asserted, not just no-panic.**
Post-fix the three bodies are lexically identical, so the target
goes further than the task text required: three-way output
equality on *every* `(next_fire_at, now, interval)` triple (fixed
adversarial battery + triples folded out of the input bytes at
24-byte stride), plus the saturation pin
(`i64::MAX` clamp or strictly-beyond-`now`, never a past value).
- **Error identity left unpinned as specified**: SQLite's
`Result<i64, String>` vs pg/mem's `InvalidSpec` — the differential
pins partition-and-value; the typed-rejection check (pg/mem must
reject with `Error::InvalidSpec`, never another variant) runs ahead
of the agreement assert.
- **Corpus growth noise after the smoke campaign**: a 180 s detached
smoke (`run-detached.sh every_parse -max_len=4096
-use_value_profile=1`, ~737k execs, 0 crash/oom/timeout — the
campaign task re-runs the full budget) grew `corpus/every_parse` to
686 files; the grown additions were pruned back to the 66 committed
generator seeds since corpus-policy reconciliation
(grown-corpus disposition, the seed-promotion posture) is the
campaign task's named AC. The `!corpus/every_parse` negation does
un-ignore grown additions in that dir — the same shape alksocks
shipped, so the tension is the campaign task's to resolve, noted
here for context.
## Summary
> To be filled on completion
Landed the `every_parse` differential target (2026-10-10): the §3.2
surface — all three one-owner `parse_every_interval` implementations
driven through the `fuzz-parser-exposure` `#[doc(hidden)]` re-exports,
plus all three `skip_forward` boundary postures.
- **`fuzz/shared/src/every_parse.rs`** — the invariant logic (stable
toolchain, replayable): typed-rejection pin (pg/mem rejects are
`Error::InvalidSpec` only), three-way agreement on partition +
`Ok` value for arbitrary lossy-decoded strings, a fixed grammar
battery (17 accept shapes with pinned interval values incl.
leading-zero and the `i64::MAX`/`i64::MAX/86400`-neighborhood
giant-`n` arms; 27 reject shapes incl. positive-zero, negative,
whitespace/truncation, cron/`@once` adjacency and unknown units),
and the overflow-posture battery over `skip_forward` (24 fixed
adversarial triples + 24-byte-stride triples folded from the raw
input; three-way equality + saturate-or-strictly-future pin).
`#[cfg(test)]` corpus replay over the committed dir (≥48 seeds).
- **`fuzz/fuzz_targets/every_parse.rs`** + `[[bin]]` entry (the
payload_codec shape); engine path deps added to `shared`'s manifest;
lib.rs module registered.
- **66 committed seeds** from `gen_fuzz_seeds.py`'s new
`every_parse()` (registry wired); `!corpus/every_parse` gitignore
negation; `fuzz/README.md` targets-table row filled.
- **Two findings found and fixed inline** (details in Notes):
`skip_forward` division-by-zero/negative-`interval` wrap (sqlite +
mem), and the i64 gap subtraction before the i128 cast (all three
engines incl. pg). PROVENANCE D-38 records the substrate delta.
- **Smoke verdict**: 180 s detached campaign, ~737k execs, 0
crash/oom/timeout — the fixes closed out the deterministic finding
space; grown corpus pruned to the committed seeds.
Verified: `cargo build` clean; `cargo test` workspace green (15 ok
result groups, 0 failures); `cargo clippy --all-targets -- -D
warnings` clean; `cargo fmt --check` clean; the shared gate
`cargo test --manifest-path fuzz/shared/Cargo.toml` green;
shared clippy `-D warnings` + fmt --check green;
`cargo fuzz build` green from `fuzz/` (nightly pin; all three engines
compile under ASAN through the new bin);
`cargo check -p alkstore-mem --target wasm32-unknown-unknown` clean.
Lineage body untouched; the substrate delta is the two-line
`skip_forward` fix in the re-derived half, registered as D-38.