From 438920f31f1badae3142255f8afdb66abf71ad9e Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Sun, 24 May 2026 12:58:26 +0200 Subject: [PATCH] chore: release v0.10.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Canonical-ABI correctness sweep — 14 commits / 15 fixes since v0.9.0, driven by the mythos-auto delta-pass on PR #179. All 33 approved loss scenarios in `safety/stpa/loss-scenarios.yaml` have matching regression tests (LS-N gate 33/33). ## Confirmed memory-safety fixes (priority high) - **LS-P-6** — `params_area_byte_size` / `return_area_byte_size` used a bare `+=` against a saturating value; once `canonical_abi_size_unpadded` saturated to `u32::MAX`, the next field's `+=` wrapped to a small value, under-sizing the params buffer and producing an OOB write in `cabi_realloc`. Now uses `saturating_add`. - **LS-P-7** — `collect_conditional_pointers` / `collect_conditional_result_pointers` computed `CopyLayout` for the whole composite payload instead of the per-leaf type, so a `list` leaf inside `option>>` got `Bulk{1}` instead of `Bulk{8}` — a 7/8 silent under-copy. New `_with_layout` collectors carry each leaf's own layout. - **LS-P-8** — Record/Tuple field-walk added the *unpadded* child size instead of `canonical_abi_element_size`, so `tuple` came out 6 instead of the spec's 12; offsets for everything downstream were wrong. Fixed at 25 field-walk sites. - **LS-P-9** — `total_flat_params` used `Iterator::sum::()` instead of saturating fold; a nested `FixedSizeList` saturating to `u32::MAX` then wrapped on the next add, selecting flat convention for a function that genuinely needed params-ptr — call-site lowering and callee-side lifting disagreed. - **LS-P-10** — Nested conditional pointer pair omitted the outer-discriminant guard. For `result, u32>` an `Err(v)` whose byte at the option slot read as 1 fired a cross-component `memory.copy` with attacker-controlled `(ptr, len)`. Added `DiscriminantGuard` + `outer_guards` chain on `ConditionalPointerPair`; the FACT adapter ANDs every guard before each copy. - **LS-P-14** — Nested-list inner copy `buf_len = callee_len * sub_elem_size` lacked the overflow guard; wraps produced truncated copies + OOB reads/writes adjacent. Added `emit_overflow_guard`. - **LS-P-16** — UTF-16→UTF-8 transcoder read 2 bytes past input for a lone high surrogate at the buffer end, leaking adjacent caller memory into the callee's UTF-8 output. Conservative mitigation traps; U+FFFD replacement upgrade is follow-up. - **LS-P-19** — UTF-8→UTF-16 mirror: each multi-byte branch unconditionally read continuation bytes at `src_idx + N` for N = 1/2/3 without bounds checking; truncated multi-byte UTF-8 leaked 1–3 bytes of caller memory into the callee's UTF-16 output. Conservative mitigation traps in each branch. ## Defensive mitigations (refusal + loud-fail) - **LS-P-12** — `list` / `list>` / `list>` silently produced stale cross-memory pointers in callee elements (the per-element conditional fixup `element_inner_pointers` cannot yet emit). `copy_layout` now panics at adapter generation rather than emitting a corrupting `Bulk` layout; structural fix tracked as follow-up. - **LS-P-18** — Refinement of LS-P-12: a record mixing a covered bare-pointer field with a hidden conditional pointer field (e.g. `record { items: list, maybe: option }`) bypassed the LS-P-12 emptiness check. New recursive `has_pointer_bearing_conditional` helper closes the bypass. ## Defensive hardening (priority low) - **LS-P-11** — Flat-name resolver overwrote duplicate module exports silently (last-writer wins); now rejects with new `Error::DuplicateModuleExport`. Unreachable for production multi-module components (the instance-graph resolver is immune), hardening for synthetic fixtures. - **LS-P-15** — Out-of-bounds `resource_type_id` was silently misclassified as callee-defined via `unwrap_or(true)`, swapping `[resource-rep]`/`[resource-new]` calls. Now drops with `log::warn!` + `continue`; downstream surfaces a loud missing-fixup error rather than silently swapping. - **LS-P-13** — Async adapter param-copy step treated every consecutive `(i32, i32)` flat-param pair as a string/list pointer pair via `.any(|_| true)` (= `!is_empty()`). Replaced with `site.requirements.pointer_pair_positions.clone()` — the resolver already returns flat indices that match the caller's lowered layout, so the heuristic walk was unneeded. - **LS-P-17** — Caller-encoding name match filtered on `ComponentTypeRef::Func` only; WIT interface imports are `Instance`, so the loop always missed and the heuristic fallback miscalibrated `string_transcoding` for mixed-encoding callers. Mitigation warns when caller has multiple distinct encodings; structural per-interface attribution is follow-up. ## Hygiene - **flat_byte_size** — `result` / `variant` payload width was `max(flat_byte_size(arm))` instead of the Component Model element-wise `flatten_variant` JOIN. Rewritten over a new `flat_width_list` helper. Hygiene-only; no in-tree consumers, no LS-N entry, no reachable hazard. ## Test coverage - 266 lib tests (+34 from v0.9.0's 232) - LS-N verification gate: 33/33 approved scenarios pinned - Full mythos delta-pass: clean on parser.rs, fact.rs, resolver.rs per-file scans - Aggregate findings + label (label-gated escape) closed by maintainer's `mythos-pass-done` after independent clean-room verification of each finding ## Process notes The mythos-auto delta-pass was the primary engine for this release: AI-driven discover.md scans on every Tier-5 PR file, each finding clean-room-verified by an independent agent following validate.md before fix-or-dispute. One false positive (auto-runner claimed LS-P-8's spec-correct `canonical_abi_element_size` should be reverted to `canonical_abi_size_unpadded` — directly contradicting `canonical-abi.py::record_size`'s `s += size(f.t)`) was disputed on the PR rather than fixed. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 2 ++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34b9b5e..c009462 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [0.10.0] - 2026-05-24 + ### Fixed - **UTF-8→UTF-16 transcoding read 1–3 bytes past the input buffer for diff --git a/Cargo.lock b/Cargo.lock index 7d1b0ef..64e1231 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1370,7 +1370,7 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "meld-cli" -version = "0.9.0" +version = "0.10.0" dependencies = [ "anyhow", "clap", @@ -1385,7 +1385,7 @@ dependencies = [ [[package]] name = "meld-core" -version = "0.9.0" +version = "0.10.0" dependencies = [ "anyhow", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 1973b9c..fccfca4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ exclude = [ ] [workspace.package] -version = "0.9.0" +version = "0.10.0" authors = ["PulseEngine "] edition = "2024" license = "Apache-2.0"