Skip to content

fix(parser): fold extended-const init/offset expressions (LS-A-11)#152

Merged
avrabe merged 1 commit into
mainfrom
fix/extended-const-truncation
May 15, 2026
Merged

fix(parser): fold extended-const init/offset expressions (LS-A-11)#152
avrabe merged 1 commit into
mainfrom
fix/extended-const-truncation

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 14, 2026

Summary

First fix from the post-v0.8.0 Mythos delta-pass sweep on the 8 Tier-5
files unscanned at v0.8.0 cut time. Two const-expression parsers in
meld-core read only the first operator and silently dropped the rest,
silently truncating any wasm 2.0 `extended-const` expression.

The bug

Site Effect
`segments.rs::parse_const_expr_with_value` Data / element segment offsets with extended-const land at wrong addresses
`merger.rs::convert_init_expr` Global initializers compute the wrong value

Concrete example: a global initialized to `(i32.const 100)(i32.const 23) i32.add` (intended value 123) was emitted as `(i32.const 100)`. A data segment with offset `(i32.const 5)(i32.const 10) i32.add` landed at offset 5 instead of 15.

wasmparser 0.246 enables `WasmFeatures::extended_const` by default, so any input authored after wit-bindgen / clang-wasi grew extended-const support can trigger this. The wasm validator accepts the truncated form because a single well-typed const is still valid; the bug is silent data corruption with no trap, affecting every downstream runtime.

Fix

New shared helpers `fold_extended_const_i32` / `fold_extended_const_i64`
in `segments.rs` walk all operators with a small stack-machine
interpreter:

```rust
loop {
let op = ops.read()?;
match op {
Operator::End => break,
Operator::I32Const { value } => stack.push(value),
Operator::I32Add => fold_i32_binop(&mut stack, i32::wrapping_add)?,
Operator::I32Sub => fold_i32_binop(&mut stack, i32::wrapping_sub)?,
Operator::I32Mul => fold_i32_binop(&mut stack, i32::wrapping_mul)?,
other => return Err(UnsupportedFeature(...)),
}
}
```

Both `parse_const_expr_with_value` and `convert_init_expr` route
their `I32Const` / `I64Const` arms through these helpers. Unsupported
operators (e.g., `global.get` mixed with arithmetic) error out
explicitly rather than silently truncating.

Tests (6 new)

  • `segments::ls_a_11_extended_const_i32_{add,sub,mul}_is_folded` — all three arithmetic ops
  • `segments::ls_a_11_single_const_still_works` — regression for simple single-const
  • `merger::ls_a_11_convert_init_expr_folds_extended_const_i32_add`
  • `merger::ls_a_11_convert_init_expr_preserves_single_const` — regression

Safety case

LS-A-11 added to `safety/stpa/loss-scenarios.yaml` under UCA-M-6 with approved status. Hazards: H-1 (semantic divergence), H-2 (wrong memory address), H-3.3 (init-expr stopped too soon).

Tier-5 gate

This PR touches `segments.rs` and `merger.rs`, both Tier-5. The new `mythos-gate` workflow will fire and request the `mythos-pass-done` label. The pass IS the work in this PR (Mythos discovery → validation via concrete PoC failure → fix → regression test).

Test plan

  • `cargo test -p meld-core --lib` — 214 pass (208 prior + 6 new)
  • `cargo clippy --all-targets -- -D warnings` — clean
  • `cargo fmt --check` — clean
  • YAML lint on safety/stpa/loss-scenarios.yaml
  • CI green on smithy runners
  • mythos-pass-done label applied

Refs

  • LS-A-11 (new, approved this PR)
  • UCA-M-6
  • H-1, H-2, H-3.3
  • Discovered by Mythos delta-pass on segments.rs and merger.rs
  • Part of post-v0.8.0 Tier-5 sweep (6 more cluster fixes pending across follow-up PRs)

🤖 Generated with Claude Code

Two const-expression parsers in meld-core read only the first operator
and silently dropped the rest:

- segments.rs::parse_const_expr_with_value parses data and element
  segment offset expressions. A data segment with offset
  (i32.const 5)(i32.const 10) i32.add landed at offset 5 instead of 15.
- merger.rs::convert_init_expr parses global initializer expressions.
  A global initialized to (i32.const 100)(i32.const 23) i32.add was
  emitted with init value 100 instead of 123.

wasmparser 0.246 enables WasmFeatures::extended_const by default, so
any input authored after wit-bindgen / clang-wasi grew extended-const
support can trigger this. Wasm validator accepts the truncated form
because a single well-typed const is still valid; the bug is silent
data corruption with no trap, affecting every downstream runtime
[H-1 semantic divergence, H-2 wrong memory address, H-3.3 init-expr
stopped too soon].

Fix:
- New shared helpers fold_extended_const_i32 / fold_extended_const_i64
  in segments.rs walk all operators with a small stack-machine
  interpreter, applying i32.add / i32.sub / i32.mul (and i64
  counterparts) with wrapping semantics, and return the folded scalar.
- segments.rs::parse_const_expr_with_value routes I32Const / I64Const
  arms through the helpers.
- merger.rs::convert_init_expr routes I32Const / I64Const arms through
  the helpers; falls back to ConstExpr::raw if folding fails.

Tests (6 new):
- segments::ls_a_11_extended_const_i32_{add,sub,mul}_is_folded
- segments::ls_a_11_single_const_still_works (regression)
- merger::ls_a_11_convert_init_expr_folds_extended_const_i32_add
- merger::ls_a_11_convert_init_expr_preserves_single_const (regression)

LS-A-11 added to safety/stpa/loss-scenarios.yaml under UCA-M-6 with
approved status. Discovered by the post-v0.8.0 Mythos delta-pass sweep
on the 8 Tier-5 files unscanned at v0.8.0 cut time (gate introduced
in #151).

Refs: LS-A-11, UCA-M-6, H-1, H-2, H-3.3

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Mythos delta-pass required

This PR modifies one or more Tier-5 source files (per
scripts/mythos/rank.md):

meld-core/src/merger.rs
meld-core/src/segments.rs

Before merge, run the Mythos discover protocol on the
modified Tier-5 files:

  1. Follow scripts/mythos/discover.md
    — one fresh agent session per touched Tier-5 file.
  2. For each finding, the agent must produce both a Kani
    harness and a failing PoC test (per the protocol's
    "if you cannot produce both, do not report" rule).
  3. Attach a comment on this PR with either the findings
    (formatted per discover.md's output schema) or
    NO FINDINGS.
  4. Add the mythos-pass-done label to this PR.

Why this gate exists: LS-A-10
(CABI alignment padding in async-lift retptr writeback) was
found by the v0.8.0 pre-release Mythos pass — but it had
lived in the callback emitter since #128, across six
releases. A PR-time gate would have caught it at review
time instead of at the release boundary.

The gate check on this PR will pass once the label is
applied.

@avrabe avrabe added the mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR label May 14, 2026
@avrabe
Copy link
Copy Markdown
Contributor Author

avrabe commented May 14, 2026

Mythos delta-pass evidence

Tier-5 files touched: meld-core/src/segments.rs, meld-core/src/merger.rs.

Pass methodology: Two fresh agents ran scripts/mythos/discover.md against the respective files in the post-v0.8.0 sweep. Both surfaced the same root cause (first-op-only const-expr parsing) as their highest-priority finding. PoCs were concrete and reproduced on current code; validation skipped per the protocol's exception ("if the PoC literally fails on current code, that IS the validation").

Result: 1 finding (LS-A-11), validated, fixed in this PR with 6 regression tests.

Adjacent findings not in this PR (will land in follow-up PRs as separate clusters):

  • segments.rs: RefNull heap-type unwrap_or(0) — reachability uncertain (cm_gc not enabled), tracking for triage
  • merger.rs: HashMap iteration non-determinism (component_realloc_index fallback, handle_tables.find()) — same shape as resolver.rs finding; will land together as cluster C2
  • merger.rs: ends_with(rn) suffix matching for resource imports — will land as cluster C3 (resource_graph + merger key matching)

@avrabe avrabe merged commit cb06f4b into main May 15, 2026
10 of 11 checks passed
@avrabe avrabe deleted the fix/extended-const-truncation branch May 15, 2026 05:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant