Repository navigation
Conversation
avrabe
force-pushed
the
v091-compexports
branch
3 times, most recently
from
November 11, 2026 15:17
d280151 to
5b9c6ed
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…decoding it as one flattened module Both decode functions walked the input with Parser::parse_all, which descends into every nested core module of a component, and had no Payload::Version arm. A component was decoded as ONE module whose index spaces were the concatenation of its nested modules': exit 0 on every backend and mode, exporting internal interfaces, omitting declared ones, leaving internal wiring undefined, and on a two-module shape binding the export `g` to the wrong body (2 under unicorn vs 101 from wasmtime's component runtime). synth_core::refuse_component_encoding now refuses every component-encoded input, first in decode_wasm_module and decode_wasm_functions and in the CLI ahead of loom/arena_bind, naming #1191 and the `meld fuse` route. Evidence: scripts/repro/component_input_1191_differential.py, red on 6b697bc (35/35 cases, 5/5 symbol tables wrong, g() = 2), green here (35/35 refused), with core-module controls executing to wasmtime's values byte-identically on both trees; three mutants each red. The new oracle declares `emulations >= 4`, held per-oracle by --floor-base (no summed pin). The home-alias audit pins move by the new core twin fixture only (+6 functions, +10 attributed), decomposed by isolation. Acceptance ladder annotated: not re-measured, corpus unmounted. Refs #1191 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
avrabe
force-pushed
the
v091-compexports
branch
from
November 12, 2026 15:24
5b9c6ed to
f6c7fa6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.91 COMPEXPORTS: refuse a WebAssembly component loudly instead of decoding it as one flattened core module
Refs #1191 · RQ-91-COMPEXPORTS
What was wrong
I ran the record's refuting command first, on main 6b697bc, and the defect is LIVE. The composed toy declares
import t:c/mmioandexport t:c/timeonly, yet the object definesT t:c/sched#state(an internal interface) and has no symbol fort:c/time#now. The compile exits 0 with no warning.The root cause is not specific to
--relocatable. Both decode functions incrates/synth-core/src/wasm_decoder.rs(decode_wasm_module,decode_wasm_functions) walk the input withParser::parse_all, which descends into every nested core module of a component. Neither had aPayload::Versionarm. A component was therefore decoded as ONE module whose function, import and export index spaces were the concatenation of its nested modules'. The order of the modules decides which symptom shows:t:c/sched#state; nothing for the declaredt:c/time#nowt:c/time#now; nothing for the declaredt:c/sched#state; 0 undefined for 1 declared importU now, which is internal wiring, beside the realU read32. The import half reproduces.gbinds to the wrong body: executed under unicorn it returns 2, while wasmtime's component runtime returns 101. Silent wrong code.U __cabi_arena_reallocfor a component that declares no imports; on self-contained Cortex-M the#418binder rewrote the component before decode and failed with a misleading "internal (bug)" errorThe change
synth_core::refuse_component_encodinguses wasmparser'sParser::is_component. It is called:maybe_run_loom/arena_bind, on all three input paths.The diagnostic names the hazard, cites #1191 and gives the supported route:
meld fuse <component.wasm> -o fused.wasm, then compile the core module.Why every component is refused, rather than a "safe subset": canonical-ABI options (string encoding, realloc, post-return) are never honoured, a lift can rename an export, one core module can be instantiated twice, and wit-component inserts shim/fixup core modules once an import needs memory. Telling a safe subset apart would take exactly the kind of hand-written analysis that produced this silent class.
Newly refused: every component-encoded input (binary layer 1, or component text) on every backend and mode. 0 pre-existing in-repo inputs are components (measured on 6b697bc). This PR adds 5 component fixtures, refused by design: they are listed in
arm_corpus_sweep_973.py'sREFUSED_BY_DESIGN, and the boot sweep counts them as declines.Acceptance ladder: NOT re-measured.
/Volumes/Work/corpora/wasm-243was not mounted. The last per-stratum figures on record (v0.62, RQ-62-REACH) accepted 6 / 5 / 5 of 112 components on arm / riscv / aarch64. Those are expected to become declines, and re-measurement is pending until the corpus is mounted. A dated note now says so beside the ladder header.Evidence:
scripts/repro/component_input_1191_differential.pyThe script is wired in
aarch64-oracle. Each fixture's declared interface is derived from wasmtime 48's own component type, and each declared export's expected value comes from wasmtime's component runtime.--expect-redon 6b697bc, and again on current main 58a9c28g()executes to 2 vs 101meld fuse, no output file written--expect-redon the branchThe paired controls pass on both trees:
f/gexecute to wasmtime's 1 / 101;Mutants (each restored after):
decode_wasm_functionsonly → unit testcomponent_1191_refused_by_decode_wasm_functionsRED (the oracle cannot reach that function in the default build);The new oracle declares
ci-checks: emulations >= 4(4 measured viaoracle_run.py:f/gof the twin and of the fused module). The branch is rebased onto main 58a9c28, which includes #1679 (EMUFLOOR), so no summed pin moves:oracle_wiring_check.py --floor-baseholds each oracle's own header against the base tree and reports "205 compared, 0 raised, 0 waived, 1 new" against 58a9c28.Local checks (on the tree rebased onto 58a9c28)
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings: clean.cargo test --workspace: 3296 passed, 0 failed.--features riscv,--features verify(its six--testtargets: 29 passed),exports_only_275_probe, andsynth-verify --features z3-solver,arm --no-runall build.synth verifyon a component also refuses with the --relocatable on a component: 6 undefined symbols where the component declares 2 imports, and the declared exports (gust:os/time) are not emitted #1191 diagnostic.prep/cc_sweep.pywithGH_TOKEN: 55/55 pass.pip install wasmtimeis unpinned and resolves to 50.0.1, which wraps component types inComponentExtern. The oracle accepts both shapes and passes red and green under 48.0.0 and 50.0.1.scripts/repro,tests/fixtures,tests/wast,tests/wat, the spec testsuite,git ls-files; 58 jobs) was run whole, step by step, on the branch. Every non-zero step is environmental, and I re-ran each one against main 58a9c28's binary on main's tree with the same result:synthpath, shellcheck/py39 variables);git diff --exit-codeassert, which saw my then-uncommitted pin edit.scripts/repro/*:arm_corpus_sweep_973.py) lists the 5 component fixtures under its existingREFUSED_BY_DESIGN(the custom-page-sizes: (memory 1 1 (pagesize 1)) compiles silently with __synth_mem_size = 0x10000 — region table over-grants, no diagnostic #1315 precedent) with the#1191needle, and passes: 223 fixtures, 196 compiled, 21 declined, 6 refused-by-design, 0 hard errors. The twin compiles and executes in it.functions audited7743 → 7749 andattributed instructions244147 → 244157;homes watchedstays 9312 andhits: 0. This is corpus growth only, decomposed by isolation. Withcomponent_1191_twin.watheld aside, this branch's binary prints main 58a9c28's 7743 / 9312 / 244147 exactly, which is also what main's binary prints over main's tree. The five components contribute 0 because they are refused before selection. Main's binary over this tree prints 7761 / 244191: it still audits the flattened components.self_contained_boot_sweep_1189, the#1229false-rejectTOTAL, the Mach-O identity sweep (one more byte-identical module, 0 disagreements) and the spec-suite census and execution steps pass with their pins unchanged.docs/status/mutation_survey.jsonis re-anchored (mutation_survey.py reanchor): 7 sites moved, 0 not found; the sample is unchanged at 38 drawn = 34 live + 4 retired.artifacts/status.jsonregenerated with no change.Rebased onto b705cdd (after #1697, #1702, #1705, #1706, #1707)
The figures above were measured on base 58a9c28. Rebasing onto 5dc4e28 conflicted only in two measured pins, and both were re-derived, not hand-merged:
functions audited: 7745,homes watched: 9312,attributed instructions: 244183,hits: 0. Paired control: withcomponent_1191_twin.watheld aside, the same binary prints main's own 7739 / 9312 / 244173. The pins are now 7745 and 244183, again corpus growth only (+6 / +10).docs/status/mutation_survey.json: main's side was taken andmutation_survey.py reanchorre-run (7 sites moved, 0 not found).The later rebase onto b705cdd (wasm-tools 0.263) was clean. On that head:
cargo metadata --locked, fmt and clippy clean;cargo test --workspace --no-fail-fast3302 passed / 0 failed; the audit prints 7745 / 9312 / 244183,hits: 0;component_input_1191_differential.pyexit 0 (emulations 4 >= 4);reanchormoves 0 sites; Claim Check 55/55; spec compile census PASS on all five backends.🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L