diff --git a/CHANGELOG.md b/CHANGELOG.md index 222b1e6..28a6f68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,57 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [0.40.0] - 2026-07-11 + +MCU-lowering release: `fuse --memory shared` is now **sound** for relocatable +inputs. This is the address-rebasing keystone that the v0.38.0 soundness gate +was holding the line for — single-address-space fusion no longer silently +corrupts memory (#326). + +**What changed:** when meld places a component's linear memory at a non-zero +base in a shared address space, it now consumes that module's relocation +metadata (`linking` + `reloc.CODE`/`reloc.DATA`, as produced by `-C +link-arg=--emit-relocs`) and rebases every `R_WASM_MEMORY_ADDR_*` site — code +address literals and inline data pointers — by the module's base. A `--memory +shared` input that lacks the metadata and performs direct memory access now +hard-errors instead of emitting a colliding module. The input contract is +**relocatable**, not PIC: a Component-Model core may import only functions, so +`wasm-tools component new` rejects a PIC/dylink core (ADR-6). + +**Falsification:** if the rebasing regressed, `test_326_reloc_const_rebasing_end_to_end` +(fuses two components and asserts, via wasmtime, that an absolute address +literal resolves to `base + addr` at runtime) would fail. If the hard-error gate +regressed, `test_326_shared_rebase_without_relocs_hard_errors` would fail. If the +legacy bulk-only dynamic rebasing regressed, `test_address_rebasing_end_to_end` +would fail. + +### Added + +- **Sound `fuse --memory shared` via relocation-metadata consumption (#326).** + New `reloc` module hand-parses `linking` v2 + `reloc.CODE`/`reloc.DATA` (the + wasmparser readers were dropped upstream). The rewriter rebases flagged + `i32.const`/`i64.const` address literals and inline data pointers through the + per-function offset map; consumed reloc sections are stripped from the output. + memarg-offset rebasing moved from blanket to reloc-driven, which also fixes a + latent over-rebasing of genuine struct-field offsets. + +### Fixed + +- **`fuse --memory shared` no longer silently corrupts memory (#326).** Absolute + addresses in a relocated component (heap/shadow-stack pointers, `static mut` + data, canonical-ABI buffer copies) are rebased into the shared window; the + runtime datapoints that motivated this (a `list` buffer reading wrong + bytes, a `static mut` store not persisting) are corrected for `--emit-relocs` + inputs. + +### Known limitations + +- A **no-reloc** module that references an absolute address purely as a *value* + (no load/store) still slips the hard-error gate (#339, Mythos Finding A — a + sound fix needs data-flow analysis). This does not affect the supported + `--emit-relocs` path. `memory64` shared inputs with 8-byte inline data + pointers are rejected rather than mis-rebased. + ## [0.39.0] - 2026-07-11 Debug-info fidelity release: two independent correctness fixes to what the diff --git a/Cargo.lock b/Cargo.lock index e45a6a6..f009772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1381,7 +1381,7 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "meld-cli" -version = "0.39.0" +version = "0.40.0" dependencies = [ "anyhow", "clap", @@ -1396,7 +1396,7 @@ dependencies = [ [[package]] name = "meld-core" -version = "0.39.0" +version = "0.40.0" dependencies = [ "anyhow", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 6abf83b..1e49156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ exclude = [ ] [workspace.package] -version = "0.39.0" +version = "0.40.0" authors = ["PulseEngine "] edition = "2024" license = "Apache-2.0" diff --git a/safety/requirements/safety-requirements.yaml b/safety/requirements/safety-requirements.yaml index a409d5d..3e01de6 100644 --- a/safety/requirements/safety-requirements.yaml +++ b/safety/requirements/safety-requirements.yaml @@ -1669,7 +1669,7 @@ artifacts: the pending "inject addr + memory_base at every load/store" idea in SR-37's history — that is unsound (it cannot distinguish pointers from integers, nor same-module from cross-module pointers). - status: proposed + status: verified tags: [memory-strategy, shared-memory, relocation, mcu, v0.40.0] links: - type: derives-from @@ -1683,18 +1683,27 @@ artifacts: release: v0.40.0 fields: implementation: + - meld-core/src/reloc.rs - meld-core/src/rewriter.rs - meld-core/src/segments.rs - meld-core/src/merger.rs verification-method: test verification-description: > - PLANNED (prototype on feat/326-reloc-consumer). Oracle fixtures from the - /tmp/spike326 spike reproduce both gale datapoints under a fused shared - memory: `reloc_326_static_addr_rebased_shared` (a `static mut` store at - an absolute `i32.const` persists across calls after rebasing — datapoint - B) and `reloc_326_data_pointer_rebased_shared` (a computed-pointer copy - preserves content — datapoint A). Negative control: a `--memory shared` - input WITHOUT `reloc.*` metadata hard-errors rather than emitting a - colliding module. Done when both oracles pass, the control errors, and - the fused output carries no stale `reloc.*` sections. + VERIFIED (#340, merged 2026-07-11). Runtime oracle + `test_326_reloc_const_rebasing_end_to_end` + (meld-core/tests/rebasing_end_to_end.rs): fuses two components into a + shared memory and, via wasmtime, asserts an absolute `i32.const` address + literal is rebased to `base + addr` (the datapoint-B `static mut` class). + Path-F negative control `test_326_shared_rebase_without_relocs_hard_errors`: + a `--memory shared` input with direct memory access and no `reloc.*` + hard-errors (`Error::MissingRelocMetadata`) instead of emitting a + colliding module. `reloc.rs` unit tests parse `linking`+`reloc.CODE`, + confirm the metadata survives `wasm-tools component new`, and + `unhandled_data_addr_relocs_flags_non_i32_pointers` gates out memory64 + 8-byte data pointers (Mythos Finding B). Existing + `test_address_rebasing_end_to_end` (bulk-only dynamic rebasing) stays + green. 457 lib + 4 integration tests pass; Mythos discover pass done. + KNOWN LIMITATION (#339, Mythos Finding A): a no-reloc module that leaks an + absolute address purely as a value (no load/store) still slips the + hard-error gate; does not affect the supported `--emit-relocs` path.