Skip to content

Rust: corrupted argument of function with signature func(record, record, u8, record) #1134

Open
@ethanstanley3

Description

Description

echo "`wit-bindgen -V` | `rustc -V` | `wasmtime -V` | `uname -m`"
wit-bindgen-cli 0.37.0 | rustc 1.83.0 (90b35a623 2024-11-26) | wasmtime 28.0.1 (1bdf2c2b5 2025-01-14) | arm64

The value of a function argument is corrupted when a host component calls a function of a guest component. The signature of the function is foo: func(a: rec, b: rec, x4: u8, d: rec), where rec is defined as follows:

record rec {
    x: s8,
    f2: string,
}

The value of foo's third argument, x4, is corrupted and overwritten by the value of d.x. The host and guest components are compiled from Rust source programs using the wit-bindgen crate and the wasm32-wasip2 target. The two components implement the WIT worlds defined below:

package ns:pkg;

world guest {
  record rec {
    x: s8,
    f2: string,
  }
  export foo: func(a: rec, b: rec, x4: u8, d: rec);
}

world host {
  record rec {
    x: s8,
    f2: string,
  }
  import foo: func(a: rec, b: rec, x4: u8, d: rec);
  export wasi:cli/[email protected];
}

package wasi:[email protected] {
  interface run {
    run: func() -> result;
  }
}

Below are the Rust source programs of the host and guest components, respectively:

fn run() -> Result<(),()> {

    let default_rec = Rec {
        x: 0, // can be anything
        f2: "".to_string(), // ^
    };

    let x4: u8 = 1; // this value should be printed, but isn't (can be anything)
    
    let special_rec = Rec {
        x: -1, // this field is magically converted to typeof(x4) and printed instead
        f2: "".to_string(), // can be anything
    };
    
    println!("Sending: {x4}");

    foo(
        &default_rec, 
        &default_rec, 
        x4, // prints x4
        &special_rec
    );
    
    Ok(())
}
fn foo(_a: Rec, _b: Rec, x4: u8, _d: Rec) {
    println!("Received: {x4}");
}

Host and guest components are created from the source programs above using the Rust toolchain. The components are composed using wac. The resulting component is executed by Wasmtime. The value of x4 is printed before and after being passed as an argument to foo.

Steps to reproduce

Here is a zipped directory that reproduces the bug:
three_records_and_int_corruption.zip

  1. Unzip three_records_and_int_corruption.zip
  2. Build and run with ./verify.sh

Expected behavior

The printed values should match:

Sending: 1
Received: 1

Actual behavior

The printed values don't match:

Sending: 1
Received: 255

Notes:
Various modifications to the test case eliminate the unexpected behavior. For example, renaming the fields of rec, changing the number/types of foo's parameters, or renaming foo's third parameter can cause the printed values to match.

Additional context

The Rust source programs are derived from programs generated by a differential testing framework for wit-bindgen. The wit definitions are derived from a test case produced by wit-smith.

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