Skip to content

fix(#257): mandatory authoritative wasm-validation backstop — loom cannot emit invalid output#260

Merged
avrabe merged 1 commit into
mainfrom
fix/257-mandatory-output-validation
Jul 9, 2026
Merged

fix(#257): mandatory authoritative wasm-validation backstop — loom cannot emit invalid output#260
avrabe merged 1 commit into
mainfrom
fix/257-mandatory-output-validation

Conversation

@avrabe

@avrabe avrabe commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #257. Makes v1.1.18's reactive #254/#255 fix systemic: turns loom's 'never emits invalid wasm' promise from 'we fixed the two passes gale found' into a guarantee by construction.

Mandatory final gate (loom-core/src/lib.rs, optimize_module)

  • Snapshot the ORIGINAL parsed module up front (after the v1.1.11 element remap scrambles the function-pointer table — valid-but-wrong code, falcon SIL gate fails (0.13m → 593.8m) #196 element-skip guard).
  • After the full pass pipeline + strip_debug_sections (the exact bytes the CLI emits), encode and run the authoritative wasmparser::validate. On rejection/encode-failure: revert the entire optimization to the original, record_revert("optimize_module:structural-invalid"), and print a loud diagnostic. Worst case = unoptimized-but-VALID output; never invalid. (Per-pass bisection noted as a follow-up refinement — not needed for the guarantee, since each pass already reverts its own invalid transforms.)

Hardened the lenient siblings (#256 per-pass pattern)

Tests (4, loom-core)

Checks

cargo test --release --workspace green (loom-core 427). fmt + clippy clean.

Part of v1.2.0 (with #240 / #259). 🤖 Generated with Claude Code

Generalize the #256 per-pass structural safety net into a systemic
guarantee: `loom optimize` can NEVER emit structurally invalid wasm.

- Mandatory final gate in `optimize_module`: snapshot the original parsed
  module up front; after the full pass pipeline, encode the optimized
  module and run the authoritative `wasmparser::validate`. On rejection
  (or encode failure), revert the ENTIRE optimization to the pristine
  original (valid, unoptimized) and emit a loud diagnostic. Worst case is
  unoptimized-but-valid output, never invalid output. Whole-optimization
  fallback-to-original is the guaranteed backstop; per-pass bisection to
  preserve maximum optimization is noted as follow-up.

- Harden the lenient siblings `constant_folding` and `simplify_locals`
  with the #256 pattern (whole-module snapshot before the pass, encode +
  `wasmparser::validate` after, revert the pass on rejection). Both used
  `translator.verify(func)` whose SKIPPED-proof path (float load/store,
  size-threshold) returns Ok and kept the transform UNCHECKED. This keeps
  failures localized so more optimization survives; the final gate remains
  the ultimate guarantee.

- No VALID transform is weakened; the gate only reverts genuinely-invalid
  output (#219/#256/inline capabilities preserved).

Regression tests (loom-core): final gate keeps the #254 fixture valid;
gate is a no-op on clean repro-219 and a hand-written clean module
(optimization preserved, not reverted); and the backstop's detect +
revert-to-original primitive turns a stack-underflow module into valid
output. `cargo test --release --workspace` green (loom-core 427 passed).

Fixes: #257

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@temper-pulseengine

Copy link
Copy Markdown
Contributor

Automated review for PR #260

pulseengine/loom:fix/257-mandatory-output-validation → pulseengine/loom:main

Verdict: 🔴 Request changes

Summary: Fixes #257 by adding a final gate to ensure loom's 'never emits invalid wasm' promise.

Findings: 7 mechanical (rivet) · 0 from local AI model.

Findings (7):

  1. 🟡 6 artifacts (rivet-validate)
    field 'evidence-type' has value 'test', allowed: ["test-report", "analysis", "simulation", "review", "field-data", "formal-proof"] — affecting: SOL-4, SOL-3, SOL-8, SOL-5, SOL-6, SOL-7

  2. 🟡 6 artifacts (rivet-validate)
    field 'goal-type' has value 'top-level', allowed: ["system-level", "element-level", "operational", "derived"] — affecting: SG-3, SG-1, SG-6, SG-4, SG-5, SG-2

  3. 🔴 6 artifacts (rivet-validate)
    Every safety goal must be supported by evidence (solution) or decomposed into sub-goals (via strategy), unless marked undeveloped
    — affecting: SG-1, SG-2, SG-3, SG-4, SG-5, SG-6

  4. 🟡 6 artifacts (rivet-validate)
    Top-level safety goals should have context defining scope and assumptions — affecting: SG-1, SG-2, SG-3, SG-4, SG-5, SG-6

  5. 🟡 6 artifacts (rivet-validate)
    STPA losses should be addressed by safety goals in the safety case — affecting: L-1, L-2, L-3, L-4, L-5, L-6

  6. 🔴 3 artifacts (rivet-validate)
    link type 'acted-on-by' is not defined in the schema — declare it in link-types: or remove the link — affecting: CP-1, CP-3, CP-2

  7. 🟡 16 artifacts (rivet-validate)
    conditional rule 'approved-needs-description': field 'description' is required when condition is met — affecting: SC-CTXT-5, SOL-7, SOL-6, SC-CTXT-1, SG-3, SOL-8, SG-1, SG-6, SG-5, SS-1 (+6 more)


Generated by a local AI model and post-validated against a strict JSON contract. Each finding includes the verbatim line being criticised — verify by reading the file at the cited location.

Reviewed at 1587192

@avrabe avrabe merged commit 096a015 into main Jul 9, 2026
23 of 25 checks passed
@avrabe avrabe deleted the fix/257-mandatory-output-validation branch July 9, 2026 02:10
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.

Harden: apply authoritative post-pass wasm validation uniformly (verify_or_revert is lenient on Z3-skip)

1 participant