fix bug with leaked imports

This commit is contained in:
vms 2020-06-07 22:57:30 +03:00
parent fe716cd078
commit bbd0941d3e
9 changed files with 134 additions and 89 deletions

View File

@ -27,14 +27,38 @@ pub(super) fn log_utf8_string(ctx: &mut Ctx, offset: i32, size: i32) {
} }
} }
pub(super) fn ipfs(ctx: &mut Ctx, offset: i32, size: i32) -> i32 {
use wasmer_core::memory::ptr::{Array, WasmPtr};
let wasm_ptr = WasmPtr::<u8, Array>::new(offset as _);
match wasm_ptr.get_utf8_string(ctx.memory(0), size as _) {
Some(msg) => println!("ipfs"),
None => println!("ipfs\n"),
}
0x1337
}
#[derive(Clone)]
struct T {}
impl Drop for T {
fn drop(&mut self) {
println!("drop T");
}
}
pub(super) fn create_host_import_func(host_cmd: String) -> DynamicFunc<'static> { pub(super) fn create_host_import_func(host_cmd: String) -> DynamicFunc<'static> {
use wasmer_core::types::Value; use wasmer_core::types::Value;
use wasmer_core::types::Type; use wasmer_core::types::Type;
use wasmer_core::types::FuncSig; use wasmer_core::types::FuncSig;
let t = T{};
let func = move |ctx: &mut Ctx, inputs: &[Value]| -> Vec<Value> { let func = move |ctx: &mut Ctx, inputs: &[Value]| -> Vec<Value> {
use wasmer_core::memory::ptr::{Array, WasmPtr}; use wasmer_core::memory::ptr::{Array, WasmPtr};
let _t = t.clone();
println!("inputs size is {}", inputs.len()); println!("inputs size is {}", inputs.len());
// TODO: refactor this // TODO: refactor this
let array_ptr = inputs[1].to_u128() as i32; let array_ptr = inputs[1].to_u128() as i32;
@ -44,9 +68,10 @@ pub(super) fn create_host_import_func(host_cmd: String) -> DynamicFunc<'static>
let wasm_ptr = WasmPtr::<u8, Array>::new(array_ptr as _); let wasm_ptr = WasmPtr::<u8, Array>::new(array_ptr as _);
match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) { match wasm_ptr.get_utf8_string(ctx.memory(0), array_size as _) {
Some(msg) => print!("{}", msg), Some(msg) => print!("{}", msg),
None => print!("ipfs node logger: incorrect UTF8 string's been supplied to logger"), None => print!("callback: incorrect UTF8 string's been supplied to logger"),
} }
vec![]
vec![Value::I32(0x1337)]
}; };
DynamicFunc::new( DynamicFunc::new(

View File

@ -81,6 +81,7 @@ impl IpfsNode {
self.process self.process
.load_module(rpc_module_name, wasm_rpc, self.rpc_module_config.clone())?; .load_module(rpc_module_name, wasm_rpc, self.rpc_module_config.clone())?;
let call_result = self.process.call( let call_result = self.process.call(
rpc_module_name, rpc_module_name,
"invoke", "invoke",
@ -131,9 +132,9 @@ impl IpfsNode {
if let Some(imports) = module_config.imports { if let Some(imports) = module_config.imports {
for (import_name, host_cmd) in imports { for (import_name, host_cmd) in imports {
println!("{} - {}", import_name, host_cmd);
let host_import = create_host_import_func(host_cmd); let host_import = create_host_import_func(host_cmd);
namespace.insert(import_name, host_import); namespace.insert(import_name, host_import);
//namespace.insert(import_name, func!(crate::imports::ipfs));
} }
} }

View File

@ -33,9 +33,9 @@ pub unsafe fn put(file_content_ptr: *mut u8, file_content_size: usize) {
log_utf8_string(msg.as_ptr() as _, msg.len() as _); log_utf8_string(msg.as_ptr() as _, msg.len() as _);
let cmd = format!("put {}", file_content); let cmd = format!("put {}", file_content);
ipfs(cmd.as_ptr() as _, cmd.len() as _); let ipfs_result = ipfs(cmd.as_ptr() as _, cmd.len() as _);
let after_ipfs = format!("after ipfs call"); let after_ipfs = format!("after ipfs call: {} \n", ipfs_result);
log_utf8_string(after_ipfs.as_ptr() as _, after_ipfs.len() as _); log_utf8_string(after_ipfs.as_ptr() as _, after_ipfs.len() as _);
let result = "IPFS node: hash is asdasdsad".to_string(); let result = "IPFS node: hash is asdasdsad".to_string();

View File

@ -35,9 +35,11 @@ pub unsafe fn invoke(file_content_ptr: *mut u8, file_content_size: usize) {
*RESULT_SIZE.get_mut(), *RESULT_SIZE.get_mut(),
*RESULT_SIZE.get_mut(), *RESULT_SIZE.get_mut(),
); );
let msg = format!("from Wasm rpc: hash is {}\n", hash);
log_utf8_string(msg.as_ptr() as _, msg.len() as _); let result_msg = format!("result from Wasm rpc: {}\n", hash);
*RESULT_PTR.get_mut() = result_msg.as_ptr() as _;
*RESULT_SIZE.get_mut() = result_msg.len();
std::mem::forget(result_msg);
} }
#[link(wasm_import_module = "host")] #[link(wasm_import_module = "host")]

View File

@ -52,14 +52,15 @@
arg.get 0 arg.get 0
string.lower_memory string.lower_memory
call-core 2 ;; call invoke call-core 2 ;; call invoke
call-core 3 ;; call get_result_size call-core 4 ;; call get_result_size
call-core 4 ;; call get_result_ptr call-core 3 ;; call get_result_ptr
string.lift_memory string.lift_memory
call-core 3 ;; call get_result_size call-core 4 ;; call get_result_size
call-core 4 ;; call get_result_ptr call-core 3 ;; call get_result_ptr
call-core 1 ;; call deallocate call-core 1 ;; call deallocate
) )
;; adapter for import function ipfs.get
(@interface func (type 9) (@interface func (type 9)
arg.get 0 arg.get 0
arg.get 1 arg.get 1
@ -70,10 +71,11 @@
call-core 0 ;; call allocate call-core 0 ;; call allocate
swap2 swap2
string.lower_memory string.lower_memory
call-core 6 ;; call set_result_size call-core 5 ;; call set_result_size
call-core 5 ;; call set_result_ptr call-core 6 ;; call set_result_ptr
) )
;; adapter for import function ipfs.put
(@interface func (type 10) (@interface func (type 10)
arg.get 0 arg.get 0
arg.get 1 arg.get 1
@ -84,8 +86,8 @@
call-core 0 ;; call allocate call-core 0 ;; call allocate
swap2 swap2
string.lower_memory string.lower_memory
call-core 6 ;; call set_result_size call-core 5 ;; call set_result_size
call-core 5 ;; call set_result_ptr call-core 6 ;; call set_result_ptr
) )
;; Implementations ;; Implementations

View File

@ -25,12 +25,12 @@ use std::collections::HashMap;
pub struct FCE { pub struct FCE {
// set of modules registered inside FCE // set of modules registered inside FCE
modules: HashMap<String, Arc<FCEModule>>, modules: HashMap<String, FCEModule>,
} }
impl Drop for FCE { impl Drop for FCE {
fn drop(&mut self) { fn drop(&mut self) {
// println!("FCE dropped"); println!("FCE dropped");
} }
} }
@ -57,9 +57,7 @@ impl WasmProcess for FCE {
) -> Result<Vec<IValue>, FCEError> { ) -> Result<Vec<IValue>, FCEError> {
match self.modules.get_mut(module_name) { match self.modules.get_mut(module_name) {
// TODO: refactor errors // TODO: refactor errors
Some(mut module) => unsafe { Some(mut module) => module.call(func_name, argument),
Ok(Arc::get_mut_unchecked(&mut module).call(func_name, argument)?)
},
None => { None => {
println!("no such module"); println!("no such module");
Err(FCEError::NoSuchModule) Err(FCEError::NoSuchModule)
@ -83,7 +81,7 @@ impl WasmProcess for FCE {
match self.modules.entry(module_name.into()) { match self.modules.entry(module_name.into()) {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
entry.insert(Arc::new(module)); entry.insert(module);
Ok(()) Ok(())
} }
Entry::Occupied(_) => Err(FCEError::NonUniqueModuleName), Entry::Occupied(_) => Err(FCEError::NonUniqueModuleName),
@ -105,7 +103,6 @@ impl WasmProcess for FCE {
match self.modules.get(module_name) { match self.modules.get(module_name) {
Some(module) => { Some(module) => {
let signatures = module let signatures = module
.as_ref()
.get_exports_signatures() .get_exports_signatures()
.map(|(name, inputs, outputs)| NodeFunction { .map(|(name, inputs, outputs)| NodeFunction {
name, name,

View File

@ -28,14 +28,36 @@ use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::sync::Arc; use std::sync::Arc;
use std::borrow::BorrowMut;
type WITInterpreter = type WITInterpreter =
Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>; Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
struct WITModuleFunc { #[derive(Clone)]
interpreter: WITInterpreter, pub(super) struct WITModuleFunc {
inputs: Vec<IType>, interpreter: Arc<WITInterpreter>,
outputs: Vec<IType>, pub(super) inputs: Vec<IType>,
pub(super) outputs: Vec<IType>,
}
#[derive(Clone)]
pub(super) struct Callable {
pub(super) wit_instance: Arc<WITInstance>,
pub(super) wit_module_func: WITModuleFunc,
}
impl Callable {
pub fn call(&mut self, args: &[IValue]) -> Result<Vec<IValue>, FCEError> {
use wasmer_wit::interpreter::stack::Stackable;
let result = self.wit_module_func
.interpreter
.run(args, Arc::make_mut(&mut self.wit_instance))?
.as_slice()
.to_owned();
Ok(result)
}
} }
pub struct FCEModule { pub struct FCEModule {
@ -43,32 +65,36 @@ pub struct FCEModule {
// that internally keep pointer to Wasmer instance. // that internally keep pointer to Wasmer instance.
#[allow(unused)] #[allow(unused)]
wamser_instance: WasmerInstance, wamser_instance: WasmerInstance,
wit_instance: Arc<WITInstance>, import_object: ImportObject,
exports_funcs: HashMap<String, WITModuleFunc>,
// TODO: replace with dyn Trait
pub(super) exports_funcs: HashMap<String, Arc<Callable>>,
} }
impl Drop for FCEModule { impl Drop for FCEModule {
fn drop(&mut self) { fn drop(&mut self) {
// println!("FCEModule dropped: {:?}", self.exports_funcs.keys()); println!("FCEModule dropped: {:?}", self.exports_funcs.keys());
} }
} }
impl FCEModule { impl FCEModule {
pub fn new( pub fn new(
wasm_bytes: &[u8], wasm_bytes: &[u8],
imports: ImportObject, fce_imports: ImportObject,
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, FCEModule>,
) -> Result<Self, FCEError> { ) -> Result<Self, FCEError> {
let wasmer_module = compile(&wasm_bytes)?; let wasmer_module = compile(&wasm_bytes)?;
let wit = extract_wit(&wasmer_module)?; let wit = extract_wit(&wasmer_module)?;
let fce_wit = FCEWITInterfaces::new(wit); let fce_wit = FCEWITInterfaces::new(wit);
let wit_exports = Self::instantiate_wit_exports(&fce_wit)?;
let mut wit_instance = Arc::new_uninit(); let mut wit_instance = Arc::new_uninit();
let mut import_object = Self::adjust_wit_imports(&fce_wit, wit_instance.clone())?; let mut import_object = Self::adjust_wit_imports(&fce_wit, wit_instance.clone())?;
import_object.extend(imports); let mut fce_imports = fce_imports;
let wasmer_instance = wasmer_module.instantiate(&import_object)?; fce_imports.extend(import_object.clone());
let wasmer_instance = wasmer_module.instantiate(&fce_imports)?;
let wit_instance = unsafe { let wit_instance = unsafe {
// get_mut_unchecked here is safe because currently only this modules have reference to // get_mut_unchecked here is safe because currently only this modules have reference to
@ -78,24 +104,21 @@ impl FCEModule {
std::mem::transmute::<_, Arc<WITInstance>>(wit_instance) std::mem::transmute::<_, Arc<WITInstance>>(wit_instance)
}; };
let exports_funcs = Self::instantiate_wit_exports(wit_instance.clone(), &fce_wit)?;
Ok(Self { Ok(Self {
wamser_instance: wasmer_instance, wamser_instance: wasmer_instance,
wit_instance, import_object,
exports_funcs: wit_exports, exports_funcs,
}) })
} }
pub fn call(&mut self, function_name: &str, args: &[IValue]) -> Result<Vec<IValue>, FCEError> { pub fn call(&mut self, function_name: &str, args: &[IValue]) -> Result<Vec<IValue>, FCEError> {
use wasmer_wit::interpreter::stack::Stackable; use wasmer_wit::interpreter::stack::Stackable;
match self.exports_funcs.get(function_name) { match self.exports_funcs.get_mut(function_name) {
Some(func) => { Some(func) => {
let result = func Arc::make_mut(func).call(args)
.interpreter
.run(args, Arc::make_mut(&mut self.wit_instance))?
.as_slice()
.to_owned();
Ok(result)
} }
None => Err(FCEError::NoSuchFunction(format!( None => Err(FCEError::NoSuchFunction(format!(
"{} hasn't been found while calling", "{} hasn't been found while calling",
@ -109,7 +132,7 @@ impl FCEModule {
function_name: &str, function_name: &str,
) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> { ) -> Result<(&Vec<IType>, &Vec<IType>), FCEError> {
match self.exports_funcs.get(function_name) { match self.exports_funcs.get(function_name) {
Some(func) => Ok((&func.inputs, &func.outputs)), Some(func) => Ok((&func.wit_module_func.inputs, &func.wit_module_func.outputs)),
None => { None => {
for func in self.exports_funcs.iter() { for func in self.exports_funcs.iter() {
println!("{}", func.0); println!("{}", func.0);
@ -126,14 +149,19 @@ impl FCEModule {
pub fn get_exports_signatures( pub fn get_exports_signatures(
&self, &self,
) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> { ) -> impl Iterator<Item = (&String, &Vec<IType>, &Vec<IType>)> {
self.exports_funcs self.exports_funcs.iter().map(|(func_name, func)| {
.iter() (
.map(|(func_name, func)| (func_name, &func.inputs, &func.outputs)) func_name,
&func.wit_module_func.inputs,
&func.wit_module_func.outputs,
)
})
} }
fn instantiate_wit_exports( fn instantiate_wit_exports(
wit_instance: Arc<WITInstance>,
wit: &FCEWITInterfaces<'_>, wit: &FCEWITInterfaces<'_>,
) -> Result<HashMap<String, WITModuleFunc>, FCEError> { ) -> Result<HashMap<String, Arc<Callable>>, FCEError> {
use fce_wit_interfaces::WITAstType; use fce_wit_interfaces::WITAstType;
wit.implementations() wit.implementations()
@ -161,14 +189,18 @@ impl FCEModule {
inputs, outputs, .. inputs, outputs, ..
} => { } => {
let interpreter: WITInterpreter = adapter_instructions.try_into()?; let interpreter: WITInterpreter = adapter_instructions.try_into()?;
let wit_module_func = WITModuleFunc {
interpreter: Arc::new(interpreter),
inputs: inputs.clone(),
outputs: outputs.clone(),
};
Ok(( Ok((
export_function_name.to_string(), export_function_name.to_string(),
WITModuleFunc { Arc::new(Callable {
interpreter, wit_instance: wit_instance.clone(),
inputs: inputs.clone(), wit_module_func,
outputs: outputs.clone(), }),
},
)) ))
} }
_ => Err(FCEError::IncorrectWIT(format!( _ => Err(FCEError::IncorrectWIT(format!(
@ -177,7 +209,7 @@ impl FCEModule {
))), ))),
} }
}) })
.collect::<Result<HashMap<String, WITModuleFunc>, FCEError>>() .collect::<Result<HashMap<String, Arc<Callable>>, FCEError>>()
} }
// this function deals only with import functions that have an adaptor implementation // this function deals only with import functions that have an adaptor implementation
@ -194,7 +226,7 @@ impl FCEModule {
impl Drop for T { impl Drop for T {
fn drop(&mut self) { fn drop(&mut self) {
// println!("drop T"); println!("fce_module imports: drop T");
} }
} }
@ -215,6 +247,8 @@ impl FCEModule {
use super::type_converters::wval_to_ival; use super::type_converters::wval_to_ival;
let t_copied = t.clone(); let t_copied = t.clone();
println!("dyn_func_from_raw_import: {:?}", inputs);
// copy here because otherwise wit_instance will be consumed by the closure // copy here because otherwise wit_instance will be consumed by the closure
let wit_instance_callable = wit_instance.clone(); let wit_instance_callable = wit_instance.clone();
let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>(); let converted_inputs = inputs.iter().map(wval_to_ival).collect::<Vec<_>>();

View File

@ -17,6 +17,7 @@
use super::wit_prelude::FCEError; use super::wit_prelude::FCEError;
use super::fce_module::FCEModule; use super::fce_module::FCEModule;
use super::{IType, IValue, WValue}; use super::{IType, IValue, WValue};
use crate::vm::module::fce_module::Callable;
use wasmer_wit::interpreter::wasm; use wasmer_wit::interpreter::wasm;
use wasmer_core::instance::DynFunc; use wasmer_core::instance::DynFunc;
@ -32,10 +33,7 @@ enum WITFunctionInner {
}, },
Import { Import {
// TODO: use dyn Callable here // TODO: use dyn Callable here
wit_module: Arc<FCEModule>, callable: Arc<Callable>,
func_name: String,
inputs: Vec<IType>,
outputs: Vec<IType>,
}, },
} }
@ -49,10 +47,10 @@ impl Drop for WITFunction {
fn drop(&mut self) { fn drop(&mut self) {
match &self.inner { match &self.inner {
WITFunctionInner::Export { func, .. } => { WITFunctionInner::Export { func, .. } => {
// println!("WITFunction export dropped: {:?}", func.signature()); println!("WITFunction export dropped: {:?}", func.signature());
} }
WITFunctionInner::Import { func_name, .. } => { WITFunctionInner::Import { callable } => {
// println!("WITFunction import dropped: {:?}", func_name); println!("WITFunction import dropped: {:?}", callable.wit_module_func.inputs);
} }
} }
} }
@ -86,18 +84,13 @@ impl WITFunction {
/// Creates function from a module import. /// Creates function from a module import.
pub(super) fn from_import( pub(super) fn from_import(
wit_module: Arc<FCEModule>, wit_module: &FCEModule,
func_name: String, func_name: String,
) -> Result<Self, FCEError> { ) -> Result<Self, FCEError> {
let func_type = wit_module.as_ref().get_func_signature(&func_name)?; let callable = wit_module.exports_funcs.get(&func_name).unwrap().clone();
let inputs = func_type.0.clone();
let outputs = func_type.1.clone();
let inner = WITFunctionInner::Import { let inner = WITFunctionInner::Import {
wit_module, callable
func_name,
inputs,
outputs,
}; };
Ok(Self { inner }) Ok(Self { inner })
@ -108,28 +101,28 @@ impl wasm::structures::LocalImport for WITFunction {
fn inputs_cardinality(&self) -> usize { fn inputs_cardinality(&self) -> usize {
match &self.inner { match &self.inner {
WITFunctionInner::Export { ref inputs, .. } => inputs.len(), WITFunctionInner::Export { ref inputs, .. } => inputs.len(),
WITFunctionInner::Import { ref inputs, .. } => inputs.len(), WITFunctionInner::Import { ref callable, .. } => callable.wit_module_func.inputs.len(),
} }
} }
fn outputs_cardinality(&self) -> usize { fn outputs_cardinality(&self) -> usize {
match &self.inner { match &self.inner {
WITFunctionInner::Export { ref outputs, .. } => outputs.len(), WITFunctionInner::Export { ref outputs, .. } => outputs.len(),
WITFunctionInner::Import { ref outputs, .. } => outputs.len(), WITFunctionInner::Import { ref callable, .. } => callable.wit_module_func.outputs.len(),
} }
} }
fn inputs(&self) -> &[IType] { fn inputs(&self) -> &[IType] {
match &self.inner { match &self.inner {
WITFunctionInner::Export { ref inputs, .. } => inputs, WITFunctionInner::Export { ref inputs, .. } => inputs,
WITFunctionInner::Import { ref inputs, .. } => inputs, WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.inputs,
} }
} }
fn outputs(&self) -> &[IType] { fn outputs(&self) -> &[IType] {
match &self.inner { match &self.inner {
WITFunctionInner::Export { ref outputs, .. } => outputs, WITFunctionInner::Export { ref outputs, .. } => outputs,
WITFunctionInner::Import { ref outputs, .. } => outputs, WITFunctionInner::Import { ref callable, .. } => &callable.wit_module_func.outputs,
} }
} }
@ -143,18 +136,9 @@ impl wasm::structures::LocalImport for WITFunction {
.map(|result| result.iter().map(wval_to_ival).collect()) .map(|result| result.iter().map(wval_to_ival).collect())
.map_err(|_| ()), .map_err(|_| ()),
WITFunctionInner::Import { WITFunctionInner::Import {
wit_module, callable
func_name,
..
} => { } => {
let mut wit_module_caller = wit_module.clone(); Arc::make_mut(&mut callable.clone()).call(arguments).map_err(|_| ())
unsafe {
// get_mut_unchecked here is safe because it is single-threaded environment
// without cyclic reference between modules
Arc::get_mut_unchecked(&mut wit_module_caller)
.call(func_name, arguments)
.map_err(|_| ())
}
} }
} }
} }

View File

@ -35,7 +35,7 @@ pub(super) struct WITInstance {
impl Drop for WITInstance { impl Drop for WITInstance {
fn drop(&mut self) { fn drop(&mut self) {
// println!("WITInstance dropped"); println!("WITInstance dropped");
} }
} }
@ -43,7 +43,7 @@ impl WITInstance {
pub(super) fn new( pub(super) fn new(
wasmer_instance: &WasmerInstance, wasmer_instance: &WasmerInstance,
wit: &FCEWITInterfaces<'_>, wit: &FCEWITInterfaces<'_>,
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, FCEModule>,
) -> Result<Self, FCEError> { ) -> Result<Self, FCEError> {
let mut exports = Self::extract_raw_exports(&wasmer_instance, wit)?; let mut exports = Self::extract_raw_exports(&wasmer_instance, wit)?;
let imports = Self::extract_imports(modules, wit, exports.len())?; let imports = Self::extract_imports(modules, wit, exports.len())?;
@ -80,7 +80,7 @@ impl WITInstance {
/// Extracts only those imports that don't have implementations. /// Extracts only those imports that don't have implementations.
fn extract_imports( fn extract_imports(
modules: &HashMap<String, Arc<FCEModule>>, modules: &HashMap<String, FCEModule>,
wit: &FCEWITInterfaces<'_>, wit: &FCEWITInterfaces<'_>,
start_index: usize, start_index: usize,
) -> Result<HashMap<usize, WITFunction>, FCEError> { ) -> Result<HashMap<usize, WITFunction>, FCEError> {
@ -92,7 +92,7 @@ impl WITInstance {
.enumerate() .enumerate()
.map(|(idx, import)| match modules.get(import.namespace) { .map(|(idx, import)| match modules.get(import.namespace) {
Some(module) => { Some(module) => {
let func = WITFunction::from_import(module.clone(), import.name.to_string())?; let func = WITFunction::from_import(module, import.name.to_string())?;
Ok((start_index + idx as usize, func)) Ok((start_index + idx as usize, func))
} }
None => Err(FCEError::NoSuchModule), None => Err(FCEError::NoSuchModule),