WasmEdge icon indicating copy to clipboard operation
WasmEdge copied to clipboard

Validation Error

Open apepkuss opened this issue 2 years ago • 3 comments

Hi @hydai @q82419,

I ran into a validation failure when I was trying to call an async wasm function from a wasm file. The detailed steps are described below. Could you please help check it? Thanks a lot!

Create and build test.wasm

I created a wasm library with the following three functions and used cargo build --target wasm32-wasi --release command to generate test.wasm:

// lib.rs

#[no_mangle]
pub async fn hundred() -> i32 {
    println!("sleep 500ms first");
    std::thread::sleep(std::time::Duration::from_millis(500));

    100
}

#[no_mangle]
pub async fn echo(num: i32) -> i32 {
    println!("sleep 500ms first");
    std::thread::sleep(std::time::Duration::from_millis(500));

    num
}

#[no_mangle]
pub async fn plus_one(num: i32) -> i32 {
    println!("sleep 500ms first");
    std::thread::sleep(std::time::Duration::from_millis(500));

    num + 1
}


// Cargo.toml

[lib]
crate-type = ["cdylib"]

The details of test.wasm are as below:

// test.wasm

(module
  (type $t0 (func (result i32)))
  (type $t1 (func (param i32 i32)))
  (type $t2 (func))
  (func $hundred (type $t0) (result i32)
    i32.const 0)
  (func $echo (type $t1) (param $p0 i32) (param $p1 i32)
    local.get $p0
    i32.const 0
    i32.store8 offset=4
    local.get $p0
    local.get $p1
    i32.store)
  (func $dummy (type $t2))
  (func $__wasm_call_dtors (type $t2)
    call $dummy
    call $dummy)
  (func $hundred.command_export (type $t0) (result i32)
    call $hundred
    call $__wasm_call_dtors)
  (func $echo.command_export (type $t1) (param $p0 i32) (param $p1 i32)
    local.get $p0
    local.get $p1
    call $echo
    call $__wasm_call_dtors)
  (func $plus_one.command_export (type $t1) (param $p0 i32) (param $p1 i32)
    local.get $p0
    local.get $p1
    call $echo
    call $__wasm_call_dtors)
  (table $T0 1 1 funcref)
  (memory $memory 16)
  (global $g0 (mut i32) (i32.const 1048576))
  (global $__heap_base i32 (i32.const 1048576))
  (global $__data_end i32 (i32.const 1048576))
  (export "memory" (memory 0))
  (export "__heap_base" (global 1))
  (export "__data_end" (global 2))
  (export "hundred" (func $hundred.command_export))
  (export "echo" (func $echo.command_export))
  (export "plus_one" (func $plus_one.command_export)))

Create and run example code

Then, I used test.wasm in the following example and tried to call the export asynchronous function plus_one:

use wasmedge_sys::{Executor, Loader, Store, WasmValue};
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let wasm_file = std::path::Path::new(
        "/Volumes/Dev/secondstate/me/issue/issue-1580/target/wasm32-wasi/release/test.wasm",
    );

    let loader = Loader::create(None)?;
    let module = loader.from_file(&wasm_file)?;

    println!("count of exports: {}", module.count_of_exports());
    module.exports().iter().for_each(|ty| {
        println!("export name: {}", ty.name());
        println!("export type: {:?}", ty.ty());
    });

    let mut executor = Executor::create(None, None)?;
    let mut store = Store::create()?;
    
    // register module 
    let instance = executor.register_named_module(&mut store, &module, "extern")?; // an error is raised in this step
    
    // get the export async function `plus_one`
    let plus_one = instance.get_func("plus_one")?;
    // call the async function
    let returns = plus_one.call(&mut executor, [WasmValue::from_i32(99)])?;
    println!("result: {}", returns[0].to_i32());

    Ok(())
}

An error is raised while registering the module into the store:

[2022-09-20 16:06:28.880] [error] wasmedge runtime failed: wasm module hasn't passed validation yet, Code: 0x08
[2022-09-20 16:06:28.880] [error]     At AST node: module
Error: Core(Common(NotValidated))

apepkuss avatar Sep 20 '22 08:09 apepkuss

Before instantiate, please validate the module by validator.

q82419 avatar Sep 20 '22 14:09 q82419

Before instantiate, please validate the module by validator.

Yes, you're right. The error disappears while doing validation with a validator instance. But a new issue appears, please help with it. I refactored the example code above, and it looks like below now:

use wasmedge_sys::{Vm, WasmValue};
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let wasm_file = std::path::Path::new("test.wasm");

    let mut vm = Vm::create(None, None)?;
    vm.register_wasm_from_file("extern", wasm_file)?;

    let async_result = vm.run_registered_function_async(
        "extern",
        "plus_one",
        [WasmValue::from_i32(10), WasmValue::from_i32(99)],
    )?;

    // get the result returned by the host function
    let returns = async_result.get_async()?;
    assert_eq!(returns.len(), 1);

    Ok(())
}

The code failed in the last assertion. The length of the actual returns is 0, but not 1. Does WasmEdge_VMAsyncExecuteRegistered interface support async wasm functions? If I was wrong in the example code above, please correct me. Thanks a lot!

apepkuss avatar Sep 20 '22 15:09 apepkuss

I'll also post the same issue to the Rust toolchain community so that we can hear the voice about the issue from the outside.

apepkuss avatar Sep 20 '22 16:09 apepkuss

Hi @apepkuss ,

Is this issue still active?

q82419 avatar Nov 04 '22 08:11 q82419