Description
Describe the bug
The execution should trap for the variants of v128.load
(e.g., v128.load32x2_s
) in llvm compiler even if the result of it is dropped. However, it executes with no errors, no traps occuring. This behavior is inconsistent with Cranelift compiler since it traps with "HeapAccessOutOfBounds" normally, no matter which optimization level is given.
use wasmer::sys::{EngineBuilder, Features};
use wasmer::{imports, Cranelift, CraneliftOptLevel, Instance, Memory, MemoryType, Module, Store, CompilerConfig};
use wasmer_compiler_llvm::{LLVM, LLVMOptLevel};
use anyhow::Error;
fn main() -> Result<(), Error> {
let diff = 1; // CHANGE HERE!!! (0 and 1)
let mut features = Features::new();
features.multi_value(true);
features.simd(true);
features.threads(true);
let engine = if diff == 0 {
let mut compiler = Cranelift::default();
compiler.canonicalize_nans(true);
compiler.opt_level(CraneliftOptLevel::None);
let engine = EngineBuilder::new(compiler).set_features(Some(features));
engine
} else {
let mut compiler = LLVM::default();
compiler.canonicalize_nans(true);
compiler.opt_level(LLVMOptLevel::None);
let engine = EngineBuilder::new(compiler).set_features(Some(features));
engine
};
let module_wat = r#"
(module
(type (;0;) (func))
(import "mem" "mem" (memory (;0;) 1))
(func (;0;) (type 0)
i32.const 0xffffffff ;; invalid memory offset
v128.load32x2_s align=1 ;; any load variants
drop)
(export "main" (func 0)))
"#;
// let module_wat = r#"
// (module
// (type (;0;) (func))
// (import "mem" "mem" (memory (;0;) 1))
// (func (;0;) (type 0)
// i32.const 0xffffffff
// v128.load align=1
// drop)
// (export "main" (func 0)))
// "#;
let mut store = Store::new(engine);
let module = Module::new(&store, &module_wat)?;
let memory_ty = MemoryType::new(1, None, false);
let memory = Memory::new(&mut store, memory_ty)?;
let imports = imports!{
"mem" => {
"mem" => memory.clone()
}
};
let instance = Instance::new(&mut store, &module, &imports)?;
let main = instance.exports.get_function("main")
.expect("`main` was not an exported function");
let result = main.call(&mut store, vec![].as_slice());
println!("{:?}", result);
Ok(())
}
[package]
name = "wasmer-wrapper"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmer = { version = "4.2.8", features = ["cranelift", "singlepass", "compiler"] }
wasmer-compiler-llvm = "4.2.8"
anyhow = "1.0"
The behavior is even not consistent with v128.load
. The execution result ends with "HeapAccessOutOfBounds" even when we use llvm compiler.
Steps to reproduce
Change the diff
value to test different compiler options. (Line 7, values with 0 and 1) Also, you can comment and uncomment the module_wat
variable as needed.
cargo run --release
Expected behavior
All executions, whichever the type of load instruction and compiler options is provided, they should trap with "HeapAccessOutOfBounds" error.
Actual behavior
Executions with variants of v128.load
and llvm compiler end with no traps. However, executions with the same code with Cranelift compiler, having the variants of v128.load
, ends with traps. Also, executions with v128.load
, which is not a variant, end with traps with llvm and Cranelift compiler.
Additional context
- llvm version: 15.0.7