Follow-up from the Mythos discover pass on the #326 reloc-consumer (PR pending).
The gap
The path-F hard-error gate (module_has_direct_memory_access in merger.rs) rejects a no-reloc, non-zero-base module only when it performs a direct load/store. It does NOT catch a module that references an absolute address purely as a value — i32.const <abs>; call $import (a canonical-ABI &BUF handed to an imported memcpy/fd_write) or i32.const <abs>; return. With no reloc metadata, the legacy path emits the const verbatim (un-rebased), so such a module hands an un-rebased pointer to the host / another component → silent cross-component corruption. This is exactly datapoint A's pattern (a buffer pointer passed to an import).
Why the naive fix is wrong (empirically confirmed)
Broadening the gate to reject any i32.const/i64.const regresses the legitimate bulk-only case: test_address_rebasing_end_to_end uses i32.const values that are safely consumed by rebased bulk-memory ops (memory.copy/fill/init, dynamically rebased by append_rebased_address). The naive broadening rejected it (test FAILED). So a bare const is indistinguishable from an integer, and bulk-op-consumed consts are safe — a sound fix needs data-flow analysis to tell an escaping address-const from a rebased-bulk-consumed or plain-integer const.
Scope / severity
- Medium. Silent memory corruption, but only on the no-reloc path (already the unsupported path — meld hard-errors the load/store subset and the error advises
--emit-relocs).
- Does NOT affect the supported path:
--emit-relocs inputs (e.g. gale's) carry reloc metadata, so their address consts are correctly rebased via reloc.CODE.
- The residual gap is documented in
module_has_direct_memory_access's doc comment (KNOWN LIMITATION).
Proposed fix
Data-flow-aware gate: reject a no-reloc non-zero-base module iff it has an i32.const/i64.const that reaches a call/call_indirect/return/store WITHOUT being consumed by a dynamically-rebased bulk-memory op. (Or: require reloc metadata for ANY no-reloc non-zero-base module with a non-trivial code section, accepting the loss of the bulk-only-without-relocs convenience — a scope decision.)
Refs #326, ADR-6 (path-F), SR-48.
Follow-up from the Mythos discover pass on the #326 reloc-consumer (PR pending).
The gap
The path-F hard-error gate (
module_has_direct_memory_accessinmerger.rs) rejects a no-reloc, non-zero-base module only when it performs a directload/store. It does NOT catch a module that references an absolute address purely as a value —i32.const <abs>; call $import(a canonical-ABI&BUFhanded to an importedmemcpy/fd_write) ori32.const <abs>; return. With no reloc metadata, the legacy path emits the const verbatim (un-rebased), so such a module hands an un-rebased pointer to the host / another component → silent cross-component corruption. This is exactly datapoint A's pattern (a buffer pointer passed to an import).Why the naive fix is wrong (empirically confirmed)
Broadening the gate to reject any
i32.const/i64.constregresses the legitimate bulk-only case:test_address_rebasing_end_to_endusesi32.constvalues that are safely consumed by rebased bulk-memory ops (memory.copy/fill/init, dynamically rebased byappend_rebased_address). The naive broadening rejected it (test FAILED). So a bare const is indistinguishable from an integer, and bulk-op-consumed consts are safe — a sound fix needs data-flow analysis to tell an escaping address-const from a rebased-bulk-consumed or plain-integer const.Scope / severity
--emit-relocs).--emit-relocsinputs (e.g. gale's) carry reloc metadata, so their address consts are correctly rebased viareloc.CODE.module_has_direct_memory_access's doc comment (KNOWN LIMITATION).Proposed fix
Data-flow-aware gate: reject a no-reloc non-zero-base module iff it has an
i32.const/i64.constthat reaches acall/call_indirect/return/storeWITHOUT being consumed by a dynamically-rebased bulk-memory op. (Or: require reloc metadata for ANY no-reloc non-zero-base module with a non-trivial code section, accepting the loss of the bulk-only-without-relocs convenience — a scope decision.)Refs #326, ADR-6 (path-F), SR-48.