mirror of
https://github.com/fluencelabs/wasmer
synced 2025-05-12 18:47:12 +00:00
fix(runtime-core) Remove undefined behavior with mem::transmute
.
In the `wrap` functions, we use `std::mem::transmute(&())` to get the pointer to the value “around” `wrap` (`Fn` has a method `to_raw` which declares a `wrap` function, which uses `transmute` to retrieve `Fn`). This is an undefined behavior. It was working until the `FuncCtx` is introduced. Since then, the undefined behavior was causing an error with the Singlepass backend. This patch stores the pointer to `Fn` in `func_env`, so that the pointer to the user-defined host function is always predictable.
This commit is contained in:
parent
a4ba429ed0
commit
c4c88f8af5
@ -517,18 +517,18 @@ macro_rules! impl_traits {
|
|||||||
let func_env = func_ctx.func_env;
|
let func_env = func_ctx.func_env;
|
||||||
|
|
||||||
let func: &FN = match func_env {
|
let func: &FN = match func_env {
|
||||||
// The imported function is a closure with a
|
// The imported function is a regular
|
||||||
// captured environment.
|
// function, a closure without a captured
|
||||||
|
// environmet, or a closure with a captured
|
||||||
|
// environment.
|
||||||
Some(func_env) => unsafe {
|
Some(func_env) => unsafe {
|
||||||
let func: NonNull<FN> = func_env.cast();
|
let func: NonNull<FN> = func_env.cast();
|
||||||
|
|
||||||
&*func.as_ptr()
|
&*func.as_ptr()
|
||||||
},
|
},
|
||||||
|
|
||||||
// The imported function is a regular function
|
// This branch is supposed to be unreachable.
|
||||||
// or a closure without a captured
|
None => unreachable!()
|
||||||
// environment.
|
|
||||||
None => unsafe { mem::transmute_copy(&()) }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Catch unwind in case of errors.
|
// Catch unwind in case of errors.
|
||||||
@ -563,7 +563,7 @@ macro_rules! impl_traits {
|
|||||||
// `FN` is a function pointer, or a closure
|
// `FN` is a function pointer, or a closure
|
||||||
// _without_ a captured environment.
|
// _without_ a captured environment.
|
||||||
if mem::size_of::<Self>() == 0 {
|
if mem::size_of::<Self>() == 0 {
|
||||||
None
|
NonNull::new(&self as *const _ as *mut vm::FuncEnv)
|
||||||
}
|
}
|
||||||
// `FN` is a closure _with_ a captured
|
// `FN` is a closure _with_ a captured
|
||||||
// environment. Grab it.
|
// environment. Grab it.
|
||||||
@ -613,18 +613,18 @@ macro_rules! impl_traits {
|
|||||||
let func_env = func_ctx.func_env;
|
let func_env = func_ctx.func_env;
|
||||||
|
|
||||||
let func: &FN = match func_env {
|
let func: &FN = match func_env {
|
||||||
// The imported function is a closure with a
|
// The imported function is a regular
|
||||||
// captured environment.
|
// function, a closure without a captured
|
||||||
|
// environmet, or a closure with a captured
|
||||||
|
// environment.
|
||||||
Some(func_env) => unsafe {
|
Some(func_env) => unsafe {
|
||||||
let func: NonNull<FN> = func_env.cast();
|
let func: NonNull<FN> = func_env.cast();
|
||||||
|
|
||||||
&*func.as_ptr()
|
&*func.as_ptr()
|
||||||
},
|
},
|
||||||
|
|
||||||
// The imported function is a regular function
|
// This branch is supposed to be unreachable.
|
||||||
// or a closure without a captured
|
None => unreachable!()
|
||||||
// environment.
|
|
||||||
None => unsafe { mem::transmute_copy(&()) }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Catch unwind in case of errors.
|
// Catch unwind in case of errors.
|
||||||
@ -656,7 +656,7 @@ macro_rules! impl_traits {
|
|||||||
// `FN` is a function pointer, or a closure
|
// `FN` is a function pointer, or a closure
|
||||||
// _without_ a captured environment.
|
// _without_ a captured environment.
|
||||||
if mem::size_of::<Self>() == 0 {
|
if mem::size_of::<Self>() == 0 {
|
||||||
None
|
NonNull::new(&self as *const _ as *mut vm::FuncEnv)
|
||||||
}
|
}
|
||||||
// `FN` is a closure _with_ a captured
|
// `FN` is a closure _with_ a captured
|
||||||
// environment. Grab it.
|
// environment. Grab it.
|
||||||
|
@ -514,12 +514,18 @@ pub struct FuncEnv {
|
|||||||
_private: [u8; 0],
|
_private: [u8; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a function context. It is used by imported function
|
/// Represents a function context. It is used by imported functions
|
||||||
/// only.
|
/// only.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(crate) struct FuncCtx {
|
pub(crate) struct FuncCtx {
|
||||||
|
/// The `Ctx` pointer.
|
||||||
pub(crate) vmctx: NonNull<Ctx>,
|
pub(crate) vmctx: NonNull<Ctx>,
|
||||||
|
|
||||||
|
/// A pointer to the function environment. It is used by imported
|
||||||
|
/// functions only to store the pointer to the real host function,
|
||||||
|
/// whether it is a regular function, or a closure with or without
|
||||||
|
/// a captured environment.
|
||||||
pub(crate) func_env: Option<NonNull<FuncEnv>>,
|
pub(crate) func_env: Option<NonNull<FuncEnv>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user