mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-24 22:21:32 +00:00
Fix execute after free issue with llvm (and presumably cranelift?)
This commit is contained in:
@ -278,7 +278,7 @@ impl LLVMBackend {
|
|||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
local_func_index: LocalFuncIndex,
|
local_func_index: LocalFuncIndex,
|
||||||
) -> Option<NonNull<vm::Func>> {
|
) -> Option<NonNull<vm::Func>> {
|
||||||
let index = local_func_index.index();
|
let index = info.imported_functions.len() + local_func_index.index();
|
||||||
let name = if cfg!(target_os = "macos") {
|
let name = if cfg!(target_os = "macos") {
|
||||||
format!("_fn{}", index)
|
format!("_fn{}", index)
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,6 +136,8 @@ pub fn parse_function_bodies(
|
|||||||
pass_manager.add_aggressive_dce_pass();
|
pass_manager.add_aggressive_dce_pass();
|
||||||
pass_manager.run_on_module(&module);
|
pass_manager.run_on_module(&module);
|
||||||
|
|
||||||
|
// module.print_to_stderr();
|
||||||
|
|
||||||
Ok((module, intrinsics))
|
Ok((module, intrinsics))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,15 +673,11 @@ fn parse_function(
|
|||||||
|
|
||||||
let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic);
|
let func_ptr_ty = llvm_sig.ptr_type(AddressSpace::Generic);
|
||||||
|
|
||||||
// Once we can just bitcast between pointer types, remove this.
|
let func_ptr = builder.build_pointer_cast(
|
||||||
let func_ptr = {
|
|
||||||
let ptr_int = builder.build_ptr_to_int(
|
|
||||||
func_ptr_untyped,
|
func_ptr_untyped,
|
||||||
intrinsics.i64_ty,
|
func_ptr_ty,
|
||||||
"func_ptr_int",
|
"typed_func_ptr",
|
||||||
);
|
);
|
||||||
builder.build_int_to_ptr(ptr_int, func_ptr_ty, "typed_func_ptr")
|
|
||||||
};
|
|
||||||
|
|
||||||
builder.build_call(func_ptr, ¶ms, &state.var_name())
|
builder.build_call(func_ptr, ¶ms, &state.var_name())
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,6 @@ impl Intrinsics {
|
|||||||
.ptr_type(AddressSpace::Generic)
|
.ptr_type(AddressSpace::Generic)
|
||||||
.as_basic_type_enum(),
|
.as_basic_type_enum(),
|
||||||
imported_func_ty
|
imported_func_ty
|
||||||
.ptr_type(AddressSpace::Generic)
|
|
||||||
.ptr_type(AddressSpace::Generic)
|
.ptr_type(AddressSpace::Generic)
|
||||||
.as_basic_type_enum(),
|
.as_basic_type_enum(),
|
||||||
sigindex_ty
|
sigindex_ty
|
||||||
@ -713,16 +712,13 @@ impl<'a> CtxType<'a> {
|
|||||||
.build_load(func_array_ptr_ptr, "func_array_ptr")
|
.build_load(func_array_ptr_ptr, "func_array_ptr")
|
||||||
.into_pointer_value();
|
.into_pointer_value();
|
||||||
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
|
let const_index = intrinsics.i32_ty.const_int(index.index() as u64, false);
|
||||||
let imported_func_ptr_ptr = unsafe {
|
let imported_func_ptr = unsafe {
|
||||||
cache_builder.build_in_bounds_gep(
|
cache_builder.build_in_bounds_gep(
|
||||||
func_array_ptr,
|
func_array_ptr,
|
||||||
&[const_index],
|
&[const_index],
|
||||||
"imported_func_ptr_ptr",
|
"imported_func_ptr",
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let imported_func_ptr = cache_builder
|
|
||||||
.build_load(imported_func_ptr_ptr, "imported_func_ptr")
|
|
||||||
.into_pointer_value();
|
|
||||||
let (func_ptr_ptr, ctx_ptr_ptr) = unsafe {
|
let (func_ptr_ptr, ctx_ptr_ptr) = unsafe {
|
||||||
(
|
(
|
||||||
cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"),
|
cache_builder.build_struct_gep(imported_func_ptr, 0, "func_ptr_ptr"),
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
use crate::export::Export;
|
use crate::export::Export;
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
|
use std::{
|
||||||
|
cell::{Ref, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait LikeNamespace {
|
pub trait LikeNamespace {
|
||||||
fn get_export(&self, name: &str) -> Option<Export>;
|
fn get_export(&self, name: &str) -> Option<Export>;
|
||||||
@ -37,14 +41,14 @@ impl IsExport for Export {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct ImportObject {
|
pub struct ImportObject {
|
||||||
map: HashMap<String, Box<dyn LikeNamespace>>,
|
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportObject {
|
impl ImportObject {
|
||||||
/// Create a new `ImportObject`.
|
/// Create a new `ImportObject`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: HashMap::new(),
|
map: Rc::new(RefCell::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +71,9 @@ impl ImportObject {
|
|||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
N: LikeNamespace + 'static,
|
N: LikeNamespace + 'static,
|
||||||
{
|
{
|
||||||
match self.map.entry(name.into()) {
|
let mut map = self.map.borrow_mut();
|
||||||
|
|
||||||
|
match map.entry(name.into()) {
|
||||||
Entry::Vacant(empty) => {
|
Entry::Vacant(empty) => {
|
||||||
empty.insert(Box::new(namespace));
|
empty.insert(Box::new(namespace));
|
||||||
None
|
None
|
||||||
@ -76,8 +82,20 @@ impl ImportObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_namespace(&self, namespace: &str) -> Option<&(dyn LikeNamespace + 'static)> {
|
pub fn get_namespace(&self, namespace: &str) -> Option<Ref<dyn LikeNamespace + 'static>> {
|
||||||
self.map.get(namespace).map(|namespace| &**namespace)
|
let map_ref = self.map.borrow();
|
||||||
|
|
||||||
|
if map_ref.contains_key(namespace) {
|
||||||
|
Some(Ref::map(map_ref, |map| &*map[namespace]))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_ref(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
map: Rc::clone(&self.map),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ impl Drop for InstanceInner {
|
|||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
module: Arc<ModuleInner>,
|
module: Arc<ModuleInner>,
|
||||||
inner: Box<InstanceInner>,
|
inner: Box<InstanceInner>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
import_object: ImportObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
@ -64,7 +66,11 @@ impl Instance {
|
|||||||
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module)
|
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module)
|
||||||
};
|
};
|
||||||
|
|
||||||
let instance = Instance { module, inner };
|
let instance = Instance {
|
||||||
|
module,
|
||||||
|
inner,
|
||||||
|
import_object: imports.clone_ref(),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(start_index) = instance.module.info.start_func {
|
if let Some(start_index) = instance.module.info.start_func {
|
||||||
instance.call_with_index(start_index, &[])?;
|
instance.call_with_index(start_index, &[])?;
|
||||||
|
@ -1,53 +1,75 @@
|
|||||||
use wasmer_runtime::{compile, error, imports, Func, Value};
|
use wasmer_runtime::{compile, error, imports, Ctx, Func, Value};
|
||||||
|
|
||||||
use wabt::wat2wasm;
|
use wabt::wat2wasm;
|
||||||
|
|
||||||
static WAT: &'static str = r#"
|
static WAT: &'static str = r#"
|
||||||
(module
|
(module
|
||||||
(type (;0;) (func (result i32)))
|
(type (;0;) (func))
|
||||||
(type (;1;) (func (param i32 i32)))
|
(type (;1;) (func))
|
||||||
(type (;2;) (func (param i32) (result i32)))
|
(type (;2;) (func))
|
||||||
(func (;0;) (type 0) (result i32)
|
(type (;3;) (func (result i32)))
|
||||||
memory.size
|
(type (;4;) (func (result i32)))
|
||||||
i32.const 65536
|
(type (;5;) (func (param i32) (result i32)))
|
||||||
i32.mul)
|
(type (;6;) (func (param i32)))
|
||||||
(func (;1;) (type 1) (param i32 i32)
|
(import "spectest" "print_i32" (func (;0;) (type 6)))
|
||||||
call 0
|
(func (;1;) (type 0))
|
||||||
|
(func (;2;) (type 1))
|
||||||
|
(func (;3;) (type 4) (result i32)
|
||||||
|
i32.const 13)
|
||||||
|
(func (;4;) (type 5) (param i32) (result i32)
|
||||||
local.get 0
|
local.get 0
|
||||||
i32.sub
|
i32.const 1
|
||||||
local.get 1
|
i32.add)
|
||||||
i32.store)
|
(func (;5;) (type 5) (param i32) (result i32)
|
||||||
(func (;2;) (type 2) (param i32) (result i32)
|
|
||||||
call 0
|
|
||||||
local.get 0
|
local.get 0
|
||||||
i32.add
|
i32.const 2
|
||||||
i32.load)
|
i32.sub)
|
||||||
(func (;3;) (type 2) (param i32) (result i32)
|
(func (;6;) (type 6) (param i32)
|
||||||
local.get 0
|
local.get 0
|
||||||
memory.grow)
|
call 0)
|
||||||
(memory (;0;) 1 2)
|
(export "one" (func 3))
|
||||||
(export "store" (func 1))
|
(export "two" (func 4))
|
||||||
(export "load" (func 2))
|
(export "three" (func 5))
|
||||||
(export "memory.grow" (func 3)))
|
(export "four" (func 6)))
|
||||||
|
"#;
|
||||||
|
|
||||||
|
static WAT2: &'static str = r#"
|
||||||
|
(module
|
||||||
|
(type $t0 (func (param i32)))
|
||||||
|
(type $t1 (func))
|
||||||
|
(func $print_i32 (export "print_i32") (type $t0) (param $lhs i32))
|
||||||
|
(func $print (export "print") (type $t1))
|
||||||
|
(table $table (export "table") 10 20 anyfunc)
|
||||||
|
(memory $memory (export "memory") 1 2)
|
||||||
|
(global $global_i32 (export "global_i32") i32 (i32.const 666)))
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
fn get_wasm() -> Vec<u8> {
|
fn get_wasm() -> Vec<u8> {
|
||||||
wat2wasm(WAT).unwrap()
|
wat2wasm(WAT).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn foobar(ctx: &mut Ctx) -> i32 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), error::Error> {
|
fn main() -> Result<(), error::Error> {
|
||||||
let wasm = get_wasm();
|
let wasm = get_wasm();
|
||||||
|
|
||||||
let module = compile(&wasm)?;
|
let module = compile(&wasm)?;
|
||||||
|
|
||||||
let imports = imports! {};
|
let import_module = compile(&wat2wasm(WAT2).unwrap())?;
|
||||||
|
let import_instance = import_module.instantiate(&imports! {})?;
|
||||||
|
|
||||||
|
let imports = imports! {
|
||||||
|
"spectest" => import_instance,
|
||||||
|
};
|
||||||
|
|
||||||
println!("instantiating");
|
println!("instantiating");
|
||||||
let instance = module.instantiate(&imports)?;
|
let instance = module.instantiate(&imports)?;
|
||||||
|
|
||||||
let foo = instance.dyn_func("store")?;
|
let foo = instance.dyn_func("four")?;
|
||||||
|
|
||||||
let result = foo.call(&[Value::I32(0), Value::I32(1)]);
|
let result = foo.call(&[Value::I32(10)]);
|
||||||
|
|
||||||
println!("result: {:?}", result);
|
println!("result: {:?}", result);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user