bytecodealliance / wasm-micro-runtime

WebAssembly Micro Runtime (WAMR)
Apache License 2.0
4.77k stars 604 forks source link

Execution results of given wasm file different from other runtime tools #2526

Open luxinyi0105 opened 1 year ago

luxinyi0105 commented 1 year ago

Test Case

The given testcase was simply mutated a wasm file, which was obtained by compiling C program generated with Csmith using Emscripten Compiler(Emcc).

The original C program is c_file.c, the compilation results with Emscripten is wasm_file.wasm, and its wat format is wat_file.wat.

We mutated the wat file to change its global.set 0 in line 43614 with local.set 0. The result after mutation is mutated_file.wat, and its wasm format is mutated_file.wasm.

Expected Results

$ iwasm --stack-size=819600000 mutated_file.wasm

Output nothing.

Actual Results

$ iwasm --stack-size=819600000 mutated_file.wasm
Exception: out of bounds memory access

Versions and Environment

Tools Version: iwasm 1.2.3 Operating system: Ubuntu 22.04.1 Architecture: x86_64

Extra Info

I tried to use some other wasm runtimes, such as wasmer, wasmedge and wasmtime to execute the same testcase, they terminate normally and do not output anything(do not trigger errors).

Maybe there is something wrong with the “exception handling module”, or related parameters while using wamr to execute the given testcase are incorrect. Due to a lack of knowledge of WebAssembly, the detail still need you to confirm.

TianlongLiang commented 11 months ago

Hi, @luxinyi0105 I just ran your test case and got the same result.

Luckily I was able to find the root of this problem. To some extent, it's not a bug, but a feature. WAMR does a rather more strict memory boundary check.

This exception arises when calling function 3, namely wasi_fd_write in L43659. If we take a look at what parameter passes to this call, there is one parameter:

;; L43650-L43651
local.get 0
i32.load offset=60

The mutated_file.wasm set global 0 rather than local 0, making it out of boundary when calling the function.

You can set the breakpoint at wasi_fd_write to see how those boundary checks happen and how the changed value of that parameter causes OOB in the case of mutated_file.wasm.

BTW, if we don't care whether wasi_fd_write to a valid address or not and comment out the L658-661 of libc_wasi_wrapper.c, we can exit with 0. I would not recommend it in any other normal case, writing to an invalid address and failing silently is actually pretty dangerous, but for this program, you just want to give it a taste, you can surely try it :)