Skip to content

fix(wrap): route lift lookup via export name + propagate string encoding (LS-A-16)#159

Merged
avrabe merged 1 commit into
mainfrom
fix/wrap-lift-string-encoding
May 16, 2026
Merged

fix(wrap): route lift lookup via export name + propagate string encoding (LS-A-16)#159
avrabe merged 1 commit into
mainfrom
fix/wrap-lift-string-encoding

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 16, 2026

Third try at LS-A-16 — the prior branches (fix/component-wrap-option-drops from PRs #155 and #158) got stuck behind a GitHub-Actions glitch where workflow_runs never triggered on synchronize events. Cherry-picked the fix onto this fresh branch name; same code.

Summary

Two defects in meld-core/src/component_wrap.rs surfaced by the post-v0.8.0 Mythos sweep:

  • find_lift_type_for_interface_func took (iface, func) parameters but never compared them. Multi-export components got every export's lift mapped to the first lift's type+options.
  • Lift emission paths hardcoded UTF-8 regardless of source string_encoding — UTF-16 lifts silently downgraded.

Fix

  • Match on the wit-bindgen {iface}#{func} export-name convention to find the right lift.
  • New source_string_encoding_option helper maps source CanonStringEncoding to the corresponding CanonicalOption.
  • Fuzz-safety fallback: when no export matches AND multi-lift, return the first lift's type/options with a log::warn — preserves fuzz_fusion_roundtrip safety for malformed inputs.

Tests (4 new)

  • ls_a_16_find_lift_distinguishes_between_two_exports
  • ls_a_16_find_lift_single_lift_fallback_still_works
  • ls_a_16_find_lift_two_lifts_without_matching_export_fuzz_safe_fallback
  • ls_a_16_source_string_encoding_option_round_trips

Refs

🤖 Generated with Claude Code

@avrabe avrabe added the mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR label May 16, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Mythos delta-pass required

This PR modifies one or more Tier-5 source files (per
scripts/mythos/rank.md):

meld-core/src/component_wrap.rs

Before merge, run the Mythos discover protocol on the
modified Tier-5 files:

  1. Follow scripts/mythos/discover.md
    — one fresh agent session per touched Tier-5 file.
  2. For each finding, the agent must produce both a Kani
    harness and a failing PoC test (per the protocol's
    "if you cannot produce both, do not report" rule).
  3. Attach a comment on this PR with either the findings
    (formatted per discover.md's output schema) or
    NO FINDINGS.
  4. Add the mythos-pass-done label to this PR.

Why this gate exists: LS-A-10
(CABI alignment padding in async-lift retptr writeback) was
found by the v0.8.0 pre-release Mythos pass — but it had
lived in the callback emitter since #128, across six
releases. A PR-time gate would have caught it at review
time instead of at the release boundary.

The gate check on this PR will pass once the label is
applied.

@avrabe avrabe force-pushed the fix/wrap-lift-string-encoding branch 2 times, most recently from dd24c2c to 258c689 Compare May 16, 2026 10:01
…ing (LS-A-16)

`find_lift_type_for_interface_func` took (iface, func) parameters but
never compared them — `let _ = target_export_name` suppressed the unused
warning. For a multi-export component, every export silently received
the first lift's type and canonical options (including string_encoding).

A guest compiled with `--string-encoding=utf16` had every export
downgraded to UTF-8 because the encoding was also hardcoded in emission
paths. Wasm validator accepts the output; downstream wasmtime transcodes
against the wrong encoding, producing mojibake / truncated strings with
no trap. Same family as the wasmtime 2026-04-09 CM-transcoding CVE wave.

Fix:
- find_lift_type_for_interface_func matches export names against the
  wit-bindgen `{iface}#{func}` convention; resolves through
  component_func_defs to the right canon Lift entry.
- New `source_string_encoding_option` helper maps the source
  CanonStringEncoding to the wasm_encoder::CanonicalOption.
- Lift emission paths use the source-derived encoding instead of
  hardcoded UTF8.
- Single-lift fallback retained for simple-fixture compatibility but
  only when exactly one lift exists; multi-lift without matching
  export now returns None instead of guessing.

Tests (4 new):
- ls_a_16_find_lift_distinguishes_between_two_exports
- ls_a_16_find_lift_single_lift_fallback_still_works
- ls_a_16_find_lift_two_lifts_without_matching_export_returns_none
- ls_a_16_source_string_encoding_option_round_trips

Deferred to a follow-up under the same UCA-W-2:
- Lower-side encoding propagation (canon.lower options threaded from
  source canon.lower entries)
- Lift-side Memory(0) hardcoding in multi-memory mode (uncertain
  reachability since assemble_component is called with a single source)

LS-A-16 added to safety/stpa/loss-scenarios.yaml. Discovered by the
post-v0.8.0 Mythos delta-pass on component_wrap.rs.

Refs: LS-A-16 (UCA-W-2, H-1, H-4)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@avrabe avrabe force-pushed the fix/wrap-lift-string-encoding branch from 258c689 to 2f60989 Compare May 16, 2026 13:17
@avrabe avrabe merged commit f21af39 into main May 16, 2026
11 of 14 checks passed
@avrabe avrabe deleted the fix/wrap-lift-string-encoding branch May 16, 2026 14:26
@avrabe avrabe mentioned this pull request May 16, 2026
3 tasks
avrabe added a commit that referenced this pull request May 16, 2026
Cuts v0.8.1 carrying the post-v0.8.0 Mythos delta-pass sweep on the 8
Tier-5 files unscanned at v0.8.0 cut time (per #151 gate scope).

Ten loss scenarios closed across 6 fix PRs, all of them silent (no
host trap, no validator rejection — wrong-by-construction outputs):

- LS-A-11 (#152) — extended-const init/offset truncation in segments
  and global initializers. Folds (i32.const x)(i32.const y) i32.add
  instead of dropping operands after the first.
- LS-A-12/13/14 (#153) — p3-async detection bugs: mixed-mode stackful
  mis-classification, stream-write over-count silently classified as
  Complete, future<stream<...>> mis-routed to stream_types via
  substring match.
- LS-A-15 (#154) — HashMap.iter().find non-determinism at three sites;
  realloc and resource-rep/-new fallbacks now sort candidate keys.
- LS-A-16 (#159) — wrapper dropped source canonical options for lifts;
  every export silently received the first lift's string encoding.
- LS-A-17/18/19 (#156) — resource_graph definer purge and terminal-
  exporter pass ignored the iface dimension; merger dedup used
  ends_with(rn) where exact match was required (float / bigfloat
  suffix collision).
- LS-A-20 (#157) — flags<N> canonical ABI silently modeled as
  Record<N x Bool>; new ComponentValType::Flags variant with explicit
  arms in every canonical-ABI helper.

Also under Added: the Mythos delta-pass CI gate workflow (#151) that
made this sweep observable at PR time, and the stackful async-lift
cross-memory (ptr, len) return path that v0.8.0 had errored out on.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant