Stream: general

Topic: wmemcheck reports Error when calling an exported alloc func


view this post on Zulip Xinyu Zeng (Dec 23 2024 at 09:08):

For a Wasm that exports an alloc function so that the host can alloc memory and then copy bytes into guest:

#[no_mangle]
pub unsafe extern "C" fn alloc(len: usize, align: usize) -> *mut u8 {
    std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(len, align))
}

When the host using the Rust embedding API to call this function in wasmtime, and wmemcheck is enabled, I got an error:

Error: error while executing at wasm backtrace:
0: 0x83 - test_wmemcheck.wasm!alloc
1: 0x2a68 - test_wmemcheck.wasm!alloc.command_export

Caused by:
Load out of bounds at addr 0x100000 of size 1

I have reduced both the host code and the guest Wasm code to a minimal example, and it still reports error. What is the reason behind this?

view this post on Zulip Lann Martin (Dec 23 2024 at 14:54):

Could you post the minimal example?

view this post on Zulip Xinyu Zeng (Dec 23 2024 at 15:04):

The host code is from the example code in the main doc

use anyhow::Result;
use wasmtime::*;

fn main() -> Result<()> {
    let engine = Engine::new(&Config::new().wmemcheck(true))?;
    let module = Module::from_file(
        &engine,
        "/home/x/wasm32-unknown-unknown/release/test_wmemcheck.wasm",
    )?;

    // Create a `Linker` which will be later used to instantiate this module.
    // Host functionality is defined by name within the `Linker`.
    let mut linker = Linker::new(&engine);
    linker.func_wrap(
        "host",
        "host_func",
        |caller: Caller<'_, u32>, param: i32| {
            println!("Got {} from WebAssembly", param);
            println!("my host state is: {}", caller.data());
        },
    )?;

    // All wasm objects operate within the context of a "store". Each
    // `Store` has a type parameter to store host-specific data, which in
    // this case we're using `4` for.
    let mut store = Store::new(&engine, 4);
    let instance = linker.instantiate(&mut store, &module)?;
    let alloc = instance.get_typed_func::<(u32, u32), (u32)>(&mut store, "alloc")?;

    // And finally we can call the wasm!
    alloc.call(&mut store, (64, 4))?;

    Ok(())
}

The wasm code is compiled to wasip1 and unknown-unknown and both reports error:

/// Allocate memory.
///
/// # Safety
///
/// See [`std::alloc::GlobalAlloc::alloc`].

#[no_mangle]
pub unsafe extern "C" fn alloc(len: usize, align: usize) -> *mut u8 {
    std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked(len, align))
}

/// Deallocate memory.
///
/// # Safety
///
/// See [`std::alloc::GlobalAlloc::dealloc`].
#[no_mangle]
pub unsafe extern "C" fn dealloc(ptr: *mut u8, len: usize, align: usize) {
    std::alloc::dealloc(
        ptr,
        std::alloc::Layout::from_size_align_unchecked(len, align),
    );
}

Last updated: Jan 24 2025 at 00:11 UTC