Files
wasmer/tests/compilers/issues.rs
2022-06-15 19:26:57 +03:00

259 lines
7.1 KiB
Rust

//! This file is mainly to assure specific issues are working well
use anyhow::Result;
use wasmer::*;
/// Corruption of WasmerEnv when using call indirect.
///
/// Note: this one is specific to Singlepass, but we want to test in all
/// available compilers.
///
/// https://github.com/wasmerio/wasmer/issues/2329
#[compiler_test(issues)]
fn issue_2329(mut config: crate::Config) -> Result<()> {
let store = config.store();
#[derive(Clone, Default, WasmerEnv)]
pub struct Env {
#[wasmer(export)]
memory: LazyInit<Memory>,
}
impl Env {
pub fn new() -> Self {
Self {
memory: LazyInit::new(),
}
}
}
pub fn read_memory(env: &Env, guest_ptr: u32) -> u32 {
dbg!(env.memory_ref());
dbg!(guest_ptr);
0
}
let wat = r#"
(module
(type (;0;) (func (param i32) (result i32)))
(type (;1;) (func))
(type (;2;) (func (param i32 i32) (result i32)))
(import "env" "__read_memory" (func $__read_memory (type 0)))
(func $read_memory (type 1)
(drop
(call $_ZN5other8dispatch17h053cb34ef5d0d7b0E
(i32.const 1)
(i32.const 2)))
(drop
(call $__read_memory
(i32.const 1))))
(func $_ZN5other8dispatch17h053cb34ef5d0d7b0E (type 2) (param i32 i32) (result i32)
(call_indirect (type 0)
(local.get 1)
(local.get 0)))
(table (;0;) 2 2 funcref)
(memory (;0;) 16)
(global (;0;) (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(global (;2;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "read_memory" (func $read_memory))
(export "__data_end" (global 1))
(export "__heap_base" (global 2))
(elem (;0;) (i32.const 1) func $__read_memory))
"#;
let module = Module::new(&store, wat)?;
let env = Env::new();
let imports: Imports = imports! {
"env" => {
"__read_memory" => Function::new_native_with_env(
&store,
env,
read_memory
),
}
};
let instance = Instance::new(&module, &imports)?;
instance.exports.get_function("read_memory")?.call(&[])?;
Ok(())
}
#[compiler_test(issues)]
fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> {
let store = config.store();
let memory = Memory::new(
&store,
MemoryType::new(Pages(1024), Some(Pages(2048)), false),
)
.unwrap();
#[derive(Clone, WasmerEnv)]
pub struct Env {
memory: Memory,
}
pub fn banana(
env: &Env,
a: u64,
b: u64,
c: u64,
d: u64,
e: u64,
f: u64,
g: u64,
h: u64,
) -> u64 {
println!("{:?}", (a, b, c, d, e, f, g, h));
let mut buf = vec![0; d as usize];
env.memory.read(e, &mut buf).unwrap();
let input_string = std::str::from_utf8(&buf).unwrap();
assert_eq!(input_string, "bananapeach");
0
}
pub fn mango(env: &Env, a: u64) {}
pub fn chaenomeles(env: &Env, a: u64) -> u64 {
0
}
pub fn peach(env: &Env, a: u64, b: u64) -> u64 {
0
}
pub fn gas(env: &Env, a: u32) {}
let wat = r#"
(module
(type (;0;) (func (param i64)))
(type (;1;) (func (param i64) (result i64)))
(type (;2;) (func (param i64 i64) (result i64)))
(type (;3;) (func (param i64 i64 i64 i64 i64 i64 i64 i64) (result i64)))
(type (;4;) (func))
(import "env" "mango" (func (;0;) (type 0)))
(import "env" "chaenomeles" (func (;1;) (type 1)))
(import "env" "peach" (func (;2;) (type 2)))
(import "env" "banana" (func (;3;) (type 3)))
(import "env" "memory" (memory (;0;) 1024 2048))
(func (;4;) (type 4)
(local i32 i64)
global.get 0
i32.const 32
i32.sub
local.tee 0
global.set 0
local.get 0
i32.const 8
i32.add
i64.const 0
i64.store
local.get 0
i64.const 0
i64.store
i64.const 0
call 0
i64.const 0
call 1
local.set 1
local.get 0
i64.const 0
i64.store offset=24
local.get 0
i64.const 0
i64.store offset=16
i64.const 0
i64.const 0
call 2
local.get 1
local.get 0
i64.extend_i32_u
i64.const 11
i32.const 1048576
i64.extend_i32_u
i64.const 0
i64.const 0
local.get 0
i32.const 16
i32.add
i64.extend_i32_u
call 3
return)
(global (;0;) (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048587))
(global (;2;) i32 (i32.const 1048592))
(global (;3;) (mut i32) (i32.const 0))
(export "memory" (memory 0))
(export "repro" (func 4))
(export "__data_end" (global 1))
(export "__heap_base" (global 2))
(data (;0;) (i32.const 1048576) "bananapeach"))
"#;
let module = Module::new(&store, wat)?;
let env = Env {
memory: memory.clone(),
};
let mut exports = Exports::new();
exports.insert("memory", memory);
exports.insert(
"banana",
Function::new_native_with_env(&store, env.clone(), banana),
);
exports.insert(
"peach",
Function::new_native_with_env(&store, env.clone(), peach),
);
exports.insert(
"chaenomeles",
Function::new_native_with_env(&store, env.clone(), chaenomeles),
);
exports.insert(
"mango",
Function::new_native_with_env(&store, env.clone(), mango),
);
exports.insert("gas", Function::new_native_with_env(&store, env, gas));
let mut imports = Imports::new();
imports.register_namespace("env", exports);
let instance = Instance::new(&module, &imports)?;
instance.exports.get_function("repro")?.call(&[])?;
Ok(())
}
/// Exhaustion of GPRs when calling a function with many floating point arguments
///
/// Note: this one is specific to Singlepass, but we want to test in all
/// available compilers.
#[compiler_test(issues)]
fn regression_gpr_exhaustion_for_calls(mut config: crate::Config) -> Result<()> {
let store = config.store();
let wat = r#"
(module
(type (;0;) (func (param f64) (result i32)))
(type (;1;) (func (param f64 f64 f64 f64 f64 f64)))
(func (;0;) (type 0) (param f64) (result i32)
local.get 0
local.get 0
local.get 0
local.get 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
f64.const 0
i32.const 0
call_indirect (type 0)
call_indirect (type 1)
drop
drop
drop
drop
i32.const 0)
(table (;0;) 1 1 funcref))
"#;
let module = Module::new(&store, wat)?;
let imports: Imports = imports! {};
let instance = Instance::new(&module, &imports)?;
Ok(())
}