Skip to content

feat(witness): Phase 2 — instrument Module::init_from_reader#133

Open
avrabe wants to merge 1 commit into
mainfrom
verify/witness-mcdc-phase2
Open

feat(witness): Phase 2 — instrument Module::init_from_reader#133
avrabe wants to merge 1 commit into
mainfrom
verify/witness-mcdc-phase2

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 24, 2026

Summary

Extends the witness MC/DC harness with a second scenario export, `try_parse_wasm(b0..b7) -> u32`, driving `Module::init_from_reader` on an 8-byte symbolic input. Phase 1's `decode_varint_5` scenario remains for LEB128 coverage. Witness now instruments two sigil-core decisions, not just one.

Result

With 7 scenarios across both exports (6 continuation-bit positions for the decoder + 7 magic/version-flip variations for the parser):

```
decisions: 0/164 full MC/DC; conditions: 2 proved, 19 gap, 583 dead

decision #0 mod.rs:456: NoWitness ← Module::init_from_reader (Phase 2)
decision #2 varint.rs:26: Partial ← LEB128 decoder (Phase 1)
decision #3 mod.rs:387: Unreached ← wasm_module parser
```

The 583 "dead" conditions are mostly `std::result` / formatting / panic-runtime machinery reachable from the harness; the meaningful signal is that witness now sees multiple sigil-core decisions through the carved verify-core.

Symmetry with the torture runner

`Module::init_from_reader` is also the function the torture-runner (PR #131) exercises against I/O fault injection. Same parser surface, measured two ways: witness for branch distinction, torture for error-path reachability. Together they form the curl-comparison rigor triangle: mutation testing (cargo-mutants, already gated) + MC/DC (witness, advancing here) + fault injection (torture-runner, PR #131).

Phase 3 — out of scope

Full MC/DC scenarios over `PublicKey::verify_multi` with crafted signed-module fixtures remain tracked on #128. That work is the test-corpus design effort the curl-comparison writeup flagged as the actual cost of MC/DC adoption — the tool is the cheap part.

Test plan

  • `cargo build --target wasm32-wasip1` clean
  • `witness instrument` + `witness run` produces a valid `run.json`
  • `witness report --format mcdc` shows both `varint.rs` and `mod.rs` decisions instrumented through verify-core

🤖 Generated with Claude Code

Adds a second scenario export, `try_parse_wasm(b0..b7) -> u32`, that
drives `Module::init_from_reader` on an 8-byte symbolic input. The
existing `decode_varint_5` scenario remains for Phase 1 (LEB128
decoder) coverage.

Result with 7 scenarios across both exports:

  decisions: 0/164 full MC/DC; conditions: 2 proved, 19 gap, 583 dead
  decision #0 mod.rs:456: NoWitness     ← Module::init_from_reader
  decision #2 varint.rs:26: Partial     ← LEB128 decoder
  decision #3 mod.rs:387: Unreached     ← wasm_module parser

Witness now instruments multiple sigil-core decisions (varint + WASM
parser), not just the single one from Phase 1. The toolchain is
demonstrated end-to-end on a second target with zero changes to
verify-core's public API.

Symmetry note: `Module::init_from_reader` is also the function the
torture-runner exercises against I/O fault injection — the same
parser surface, measured two ways (witness for branch distinction,
torture for error-path reachability).

Phase 3 — full MC/DC scenarios over `PublicKey::verify_multi` with
crafted signed-module fixtures — remains tracked on #128. That work
is the test-corpus design effort the curl-comparison flagged as the
actual cost of MC/DC adoption (the tool is the cheap part).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant