diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b9226707..a932aace7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - [#2149](https://github.com/wasmerio/wasmer/pull/2144) `wasmer-engine-native` looks for clang-11 instead of clang-10. ### Fixed +- [#2210](https://github.com/wasmerio/wasmer/pull/2210) Fix a memory leak in the Wasm C API in the strings used to identify imports and exports coming from user code. - [#2108](https://github.com/wasmerio/wasmer/pull/2108) The Object Native Engine generates code that now compiles correctly with C++. - [#2125](https://github.com/wasmerio/wasmer/pull/2125) Fix RUSTSEC-2021-0023. - [#2155](https://github.com/wasmerio/wasmer/pull/2155) Fix the implementation of shift and rotate in the LLVM compiler. diff --git a/lib/c-api/src/wasm_c_api/types/export.rs b/lib/c-api/src/wasm_c_api/types/export.rs index 6a78805cb..a2d94d3c0 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -1,10 +1,10 @@ -use super::{wasm_externtype_t, wasm_name_t}; +use super::{owned_wasm_name_t, wasm_externtype_t, wasm_name_t}; use wasmer::ExportType; #[allow(non_camel_case_types)] #[derive(Clone)] pub struct wasm_exporttype_t { - name: Box, + name: owned_wasm_name_t, extern_type: Box, } @@ -12,11 +12,12 @@ wasm_declare_boxed_vec!(exporttype); #[no_mangle] pub extern "C" fn wasm_exporttype_new( - name: Option>, + name: Option<&wasm_name_t>, extern_type: Option>, ) -> Option> { + let name = unsafe { owned_wasm_name_t::new(name?) }; Some(Box::new(wasm_exporttype_t { - name: name?, + name, extern_type: extern_type?, })) } @@ -42,7 +43,7 @@ impl From for wasm_exporttype_t { impl From<&ExportType> for wasm_exporttype_t { fn from(other: &ExportType) -> Self { - let name: Box = Box::new(other.name().to_string().into()); + let name: owned_wasm_name_t = other.name().to_string().into(); let extern_type: Box = Box::new(other.ty().into()); wasm_exporttype_t { name, extern_type } diff --git a/lib/c-api/src/wasm_c_api/types/import.rs b/lib/c-api/src/wasm_c_api/types/import.rs index 9d060584d..8e2e5361c 100644 --- a/lib/c-api/src/wasm_c_api/types/import.rs +++ b/lib/c-api/src/wasm_c_api/types/import.rs @@ -1,11 +1,12 @@ -use super::{wasm_externtype_t, wasm_name_t}; +use super::{owned_wasm_name_t, wasm_externtype_t, wasm_name_t}; use wasmer::ImportType; #[allow(non_camel_case_types)] #[derive(Clone)] +#[repr(C)] pub struct wasm_importtype_t { - module: Box, - name: Box, + module: owned_wasm_name_t, + name: owned_wasm_name_t, extern_type: Box, } @@ -13,13 +14,19 @@ wasm_declare_boxed_vec!(importtype); #[no_mangle] pub extern "C" fn wasm_importtype_new( - module: Option>, - name: Option>, + module: Option<&wasm_name_t>, + name: Option<&wasm_name_t>, extern_type: Option>, ) -> Option> { + let (module, name) = unsafe { + ( + owned_wasm_name_t::new(module?), + owned_wasm_name_t::new(name?), + ) + }; Some(Box::new(wasm_importtype_t { - name: name?, - module: module?, + name, + module, extern_type: extern_type?, })) } @@ -50,8 +57,8 @@ impl From for wasm_importtype_t { impl From<&ImportType> for wasm_importtype_t { fn from(other: &ImportType) -> Self { - let module: Box = Box::new(other.module().to_string().into()); - let name: Box = Box::new(other.name().to_string().into()); + let module: owned_wasm_name_t = other.module().to_string().into(); + let name: owned_wasm_name_t = other.name().to_string().into(); let extern_type: Box = Box::new(other.ty().into()); wasm_importtype_t { diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index c022ba17e..541747045 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -28,16 +28,63 @@ wasm_declare_vec!(byte); #[allow(non_camel_case_types)] pub type wasm_name_t = wasm_byte_vec_t; -impl From for wasm_name_t { +impl AsRef for wasm_name_t { + fn as_ref(&self) -> &wasm_name_t { + &self + } +} + +/// An owned version of `wasm_name_t`. +/// +/// Assumes that data is either valid host-owned or null. +// NOTE: `wasm_name_t` already does a deep copy, so we just derive `Clone` here. +#[derive(Debug, Clone)] +#[repr(transparent)] +#[allow(non_camel_case_types)] +pub struct owned_wasm_name_t(wasm_name_t); + +impl owned_wasm_name_t { + /// Take ownership of some `wasm_name_t` + /// + /// # Safety + /// You must ensure that the data pointed to by `wasm_name_t` is valid and + /// that it is not owned by anyone else. + pub unsafe fn new(name: &wasm_name_t) -> Self { + Self(wasm_name_t { + size: name.size, + data: name.data, + }) + } +} + +impl Drop for owned_wasm_name_t { + fn drop(&mut self) { + if !self.0.data.is_null() { + let _v = unsafe { Vec::from_raw_parts(self.0.data, self.0.size, self.0.size) }; + self.0.data = std::ptr::null_mut(); + self.0.size = 0; + } + // why can't we call this function? + //unsafe { crate::wasm_c_api::macros::wasm_byte_vec_delete(Some(self.0)) } + } +} + +impl AsRef for owned_wasm_name_t { + fn as_ref(&self) -> &wasm_name_t { + &self.0 + } +} + +impl From for owned_wasm_name_t { fn from(string: String) -> Self { let mut boxed_str: Box = string.into_boxed_str(); let data = boxed_str.as_mut_ptr(); let size = boxed_str.bytes().len(); - let wasm_name = Self { data, size }; + let wasm_name = wasm_name_t { data, size }; Box::leak(boxed_str); - wasm_name + Self(wasm_name) } } diff --git a/lib/c-api/src/wasm_c_api/unstable/wasi.rs b/lib/c-api/src/wasm_c_api/unstable/wasi.rs index 8eb0a5fa2..8fce17709 100644 --- a/lib/c-api/src/wasm_c_api/unstable/wasi.rs +++ b/lib/c-api/src/wasm_c_api/unstable/wasi.rs @@ -2,7 +2,10 @@ //! API. use super::super::{ - externals::wasm_extern_t, module::wasm_module_t, store::wasm_store_t, types::wasm_name_t, + externals::wasm_extern_t, + module::wasm_module_t, + store::wasm_store_t, + types::{owned_wasm_name_t, wasm_name_t}, wasi::wasi_env_t, }; use crate::error::CApiError; @@ -19,8 +22,8 @@ use wasmer_wasi::{generate_import_object_from_env, get_wasi_version}; #[allow(non_camel_case_types)] #[derive(Clone)] pub struct wasmer_named_extern_t { - module: Box, - name: Box, + module: owned_wasm_name_t, + name: owned_wasm_name_t, r#extern: Box, } @@ -179,8 +182,8 @@ fn wasi_get_unordered_imports_inner( *imports = import_object .into_iter() .map(|((module, name), export)| { - let module = Box::new(module.into()); - let name = Box::new(name.into()); + let module = module.into(); + let name = name.into(); let extern_inner = Extern::from_vm_export(store, export); Box::new(wasmer_named_extern_t {