Skip to content

Adapter lowering corrupts string data in option/variant/flavorful types #14

@avrabe

Description

@avrabe

Context

Adding wit-bindgen fixtures for variants, options, and flavorful type families (issue #10) revealed that fusion + validation pass, but runtime execution traps due to corrupted string data in cross-component calls.

Reproduction

With fixtures generated from wit-bindgen v0.52.0:

cargo test --package meld-core --test wit_bindgen_runtime test_runtime_wit_bindgen_options

Observed behavior

  • options: option<string> roundtrip produces Some("189") instead of Some("foo")
  • flavorful: list-in-variant tests produce "\u{1e}\0\0" instead of "foo"
  • variants: variant types with string payloads produce corrupted data

The string pointer/length pairs are being read from wrong offsets or wrong memory after adapter lowering.

Root cause

The adapter code path for identifying pointer pairs in function parameters (collect_pointer_positions in parser.rs:1315-1343) explicitly ignores Option, Result, and Variant types:

// Scalars, options, results, resources — no pointer pairs at param level
_ => {}

In the Canonical ABI, option<string> flattens to [i32(discriminant), i32(ptr), i32(len)]. Since the resolver reports no pointer pairs for these types, the adapter does not copy the string data across memories. The callee receives a pointer that references the caller's memory, reading garbage.

Fix needed

collect_pointer_positions and collect_pointer_byte_offsets must recurse into:

  • Option<T> — discriminant at offset 0, then payload at offset 1
  • Result<T,E> — discriminant at offset 0, then ok/err payload at offset 1
  • Variant — discriminant at offset 0, then case payloads at offset 1

The adapter must emit conditional copy logic: only copy the pointer data when the discriminant indicates the variant is active (e.g., Some for option, Ok/Err for result).

This requires:

  1. Extending pointer_pair_positions to include option/result/variant payloads
  2. Generating conditional if discriminant == X then copy blocks in the adapter
  3. Handling the case where different variant arms have different layouts (e.g., result<string, u32>)

Affected code

  • meld-core/src/parser.rs: collect_pointer_positions, collect_pointer_byte_offsets
  • meld-core/src/adapter/fact.rs: generate_memory_copy_adapter, generate_retptr_adapter
  • meld-core/src/resolver.rs: collect_param_copy_layouts, collect_result_copy_layouts

STPA traceability

  • SR-16 (recursive inner pointer fixup)
  • LS-R-2 (CopyLayout misclassification)
  • UCA-A-7 (wrong element stride)

Affected tests

Tests are currently handled with graceful degradation (log + skip):

  • test_runtime_wit_bindgen_variants
  • test_runtime_wit_bindgen_options
  • test_runtime_wit_bindgen_flavorful

Fusion (CoreModule + Component) tests pass for all three. ref #10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions