fix(parser): canonical ABI for flags<N> (LS-A-20)#157
Conversation
|
Mythos delta-pass evidence Tier-5 files touched: The agent that ran The fix touches adapter/fact.rs and component_wrap.rs only to extend pattern-match coverage to the new No adjacent findings from parser.rs scan deferred — this is the only strong one. |
Mythos delta-pass requiredThis PR modifies one or more Tier-5 source files (per Before merge, run the Mythos discover protocol on the
Why this gate exists: LS-A-10 The gate check on this PR will pass once the label is |
parser::convert_wp_defined_type mapped Component-Model flags<N> to
ComponentValType::Record(N × Bool), so downstream canonical-ABI
helpers computed flat=N, size=N bytes, align=1.
Spec for flags<N>:
- flat_count = ceil(N/32) i32 storage words
- size = ceil(N/8) padded to power-of-2 storage class
- align ∈ {1, 2, 4} from the storage class
Concrete impact: flags<17> as a parameter had flat=17 in meld but
flat=1 per spec. Resolver's params-ptr threshold fires at >16, so meld
flipped into params-ptr calling convention while producer kept the
flat path. Smaller N (flags<9>) produced wrong size (9 vs 2) and wrong
alignment.
Bug existed since the Flags arm was added (~2026-03-09), ~2 months
multiple releases. Wasm validator doesn't catch it because the
truncated layout is internally consistent within meld's pipeline.
Fix:
- New ComponentValType::Flags(Vec<String>) variant
- Parser's Flags arm produces it directly
- Explicit Flags arms in flat_count / canonical_abi_align /
canonical_abi_size_unpadded / flat_byte_size /
collect_return_area_type_slots / cabi_size_align /
flat_component_val_type_resolved / resolve_component_val_type
- u32::div_ceil(32) for word count (overflow-safe, Rust 1.73+ stable
API; replaces (n + 31) / 32 which clippy now flags)
Tests (2 new):
- ls_a_20_flags_canonical_abi_matches_spec (N=1/8/9/17/32/33)
- ls_a_20_flags_parser_produces_flags_variant (wat round-trip)
LS-A-20 added to safety/stpa/loss-scenarios.yaml under UCA-P-10 with
approved status. Discovered by the post-v0.8.0 Mythos delta-pass on
parser.rs.
Refs: LS-A-20 (UCA-P-10, H-4, H-4.1)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5680cda to
e286b04
Compare
Sixth fix from the post-v0.8.0 Mythos delta-pass sweep. The parser bridge at
convert_wp_defined_typemapped Component-Modelflags<N>toComponentValType::Record(N × Bool), so the downstream canonical-ABI helpers computed wrong flat/size/align values.The bug
flat_count(flags<N>)ceil(N/32)N(one per Bool field)size(flags<N>)ceil(N/8)padded to power-of-2 storage classN(one byte per Bool)align(flags<N>)Concrete impact: a function taking
flags<17>hadflat=17in meld butflat=1per spec. The resolver's params-ptr threshold fires attotal_flat_params > 16, so meld flipped into params-ptr calling convention while the producer kept on the flat path — silent calling-convention mismatch between fused and composed paths.Smaller N (e.g.
flags<9>) produced wrong size (9 vs spec's 2) and wrong alignment, mis-aligning adjacent record fields. The bug shipped since March 2026 (~2 months, multiple releases). Wasm validator did not catch it because the truncated layout is internally consistent within meld's own pipeline.Fix
ComponentValType::Flags(Vec<String>)variant (preserves flag names for diagnostics).Record<N × Bool>.ComponentValType:flat_count,canonical_abi_align,canonical_abi_size_unpadded,flat_byte_size,collect_return_area_type_slots,resolve_component_val_type,cabi_size_align(adapter/fact.rs), andflat_component_val_type_resolved(component_wrap.rs).u32::div_ceil(32)for overflow-safe ceiling division (clippy's modern-API lint).Tests (2 new)
ls_a_20_flags_canonical_abi_matches_spec— exhaustive across N=1/8/9/17/32/33 to exercise every storage-class transition.ls_a_20_flags_parser_produces_flags_variant— wat round-trip asserting the parser emitsComponentValType::Flags(notRecord<Bool>).Tier-5 gate
Touches
parser.rs(Tier-5),adapter/fact.rs(Tier-5),component_wrap.rs(Tier-5).Test plan
cargo test -p meld-core --lib— 210 pass (208 prior + 2 new)cargo clippy --all-targets -- -D warnings— cleancargo fmt --check— cleanRefs
🤖 Generated with Claude Code