You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Move trap-preservation from guards around the validator to the validator's encoding itself: verify refinement, not value-equivalence, with traps as a first-class component of the abstract state. This is Alive2's central design decision, and it is the named, published answer to the exact class loom shipped five times (#273/#274/#276/#278/#281).
Why the current shape leaves the hole open
The Z3 translation validator proves value equivalence over a model in which every Wasm operation is total — traps are unmodelled. trap_gate.rs says so directly, and that is why an identity rewrite (x * 0 → 0, dropping a dead div result, constant-condition select) could be certified equivalent while deleting a mandatory trap.
The current defence is sound but structural: a recursive trap-freedom guard (is_no_trap_expr / is_forwardable_expr) gates ~25 fold sites, with trap_backstop.rs calling into trap_gate. That is a per-rule allowlist. The residual risk is exactly the one the research names: a new rewrite added tomorrow is trap-unsafe by default and only safe if its author remembers the guard. The oracle still cannot see traps; we are relying on the guard never being forgotten.
The load-bearing decision: the correctness relation is refinement, not equality — a transformation may only eliminate non-determinism/UB, never introduce it, degenerating to equivalence only when no UB exists. UB, poison and undef are modelled as first-class parts of the abstract state, so an optimization that removes a mandatory error condition is a refinement violation and is rejected by construction — no allowlist required.
Empirical warrant, and the part that should interest us most: running Alive2 over LLVM's own unit tests found 47 new bugs (28 fixed) and forced 8 patches to the LLVM Language Reference. Building a trap-faithful encoding is itself what exposed that the specification was underspecified. That is our recurring fault class, and it means this work pays off twice.
Concretely
Encode trap as state. Extend the validator's abstract state with an explicit trap/⊥ component per Wasm trapping op (div/rem by zero, INT_MIN / -1, OOB load/store, unreachable, indirect-call type mismatch).
Switch the relation to refinement.optimized ⊑ original: for every input, if the original traps the optimized may do anything; if the original does not trap, the optimized must not trap and must agree on values. Deleting a reachable trap becomes unprovable — the encoding rejects it without any syntactic guard.
Then demote the guards to a backstop. Keep is_no_trap_expr as defence-in-depth, but stop it being the primary mechanism.
This is a real piece of work, not a config change, and Alive2 is bounded (it validates within bounds, not a whole-compiler proof). The claim here is only that it converts a class of "green but wrong" into "unprovable", which is exactly the trade we want.
Ask
Move trap-preservation from guards around the validator to the validator's encoding itself: verify refinement, not value-equivalence, with traps as a first-class component of the abstract state. This is Alive2's central design decision, and it is the named, published answer to the exact class loom shipped five times (#273/#274/#276/#278/#281).
Why the current shape leaves the hole open
The Z3 translation validator proves value equivalence over a model in which every Wasm operation is total — traps are unmodelled.
trap_gate.rssays so directly, and that is why an identity rewrite (x * 0 → 0, dropping a dead div result, constant-conditionselect) could be certified equivalent while deleting a mandatory trap.The current defence is sound but structural: a recursive trap-freedom guard (
is_no_trap_expr/is_forwardable_expr) gates ~25 fold sites, withtrap_backstop.rscalling intotrap_gate. That is a per-rule allowlist. The residual risk is exactly the one the research names: a new rewrite added tomorrow is trap-unsafe by default and only safe if its author remembers the guard. The oracle still cannot see traps; we are relying on the guard never being forgotten.The prior art (this is not new theory)
Alive2: Bounded Translation Validation for LLVM — Lopes, Lee, Hur, Liu, Regehr, PLDI 2021 (paper, repo).
The load-bearing decision: the correctness relation is refinement, not equality — a transformation may only eliminate non-determinism/UB, never introduce it, degenerating to equivalence only when no UB exists. UB, poison and undef are modelled as first-class parts of the abstract state, so an optimization that removes a mandatory error condition is a refinement violation and is rejected by construction — no allowlist required.
Empirical warrant, and the part that should interest us most: running Alive2 over LLVM's own unit tests found 47 new bugs (28 fixed) and forced 8 patches to the LLVM Language Reference. Building a trap-faithful encoding is itself what exposed that the specification was underspecified. That is our recurring fault class, and it means this work pays off twice.
Concretely
INT_MIN / -1, OOB load/store,unreachable, indirect-call type mismatch).optimized ⊑ original: for every input, if the original traps the optimized may do anything; if the original does not trap, the optimized must not trap and must agree on values. Deleting a reachable trap becomes unprovable — the encoding rejects it without any syntactic guard.is_no_trap_expras defence-in-depth, but stop it being the primary mechanism.Honest note
This is a real piece of work, not a config change, and Alive2 is bounded (it validates within bounds, not a whole-compiler proof). The claim here is only that it converts a class of "green but wrong" into "unprovable", which is exactly the trade we want.