From a4effaaffe5f9dc6dd55b82e53a9b91fd323343e Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 11:34:33 +0100 Subject: [PATCH 01/16] test+doc(c-api) Continue to improve test coverage of the C API. --- lib/c-api/src/wasm_c_api/macros.rs | 59 ++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index f0225f3ddd2..92dd1590206 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -3,8 +3,31 @@ macro_rules! wasm_declare_vec_inner { ($name:ident) => { paste::paste! { - /// Creates an empty vector of - #[doc = "Creates an empty vector of [`wasm_" $name "_t`]."] + #[doc = "Creates an empty vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_empty(&vector); + + // Check that it is empty. + assert(vector.size == 0); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut []) { // TODO: actually implement this @@ -19,7 +42,37 @@ macro_rules! wasm_declare_vec_inner { macro_rules! wasm_declare_vec { ($name:ident) => { paste::paste! { - #[doc = "Represents of a vector of [`wasm_" $name "_t`]."] + #[doc = "Represents of a vector of `wasm_" $name "_t`. + +Read the documentation of [`wasm_" $name "_t`] to see more concrete examples. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Create a vector of 2 `wasm_" $name "_t`. + wasm_" $name "_t x; + wasm_" $name "_t y; + wasm_" $name "_t* items[2] = {&x, &y}; + + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new(&vector, 2, (wasm_" $name "_t*) items); + + // Check that it contains 2 items. + assert(vector.size == 2); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[derive(Debug)] #[repr(C)] pub struct [] { From e10ad512bcdcac420d0f1206b48e33aae0833c75 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 13:51:41 +0100 Subject: [PATCH 02/16] fix(c-api) Fix how `wasm_functype_t` is implemented. In `wasm.h`, `wasm_functype_t` is implemented with `WASM_DECLARE_TYPE`, so with `WASM_DECLARE_VEC(functype, *)`. This `*` means the C struct for the vector is defined: ```c struct wasm_functype_vec_t { size_t size; wasm_functype_t** data; } ``` The way we implement `wasm_functype_vec_t` in Rust is with the `wasm_declare_vec!` macro. And it is wrong. We must use `wasm_declared_boxed_vec!`. --- lib/c-api/src/wasm_c_api/types/function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 35b845481d6..cf8cfeaa347 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -90,7 +90,7 @@ impl wasm_functype_t { } } -wasm_declare_vec!(functype); +wasm_declare_boxed_vec!(functype); #[no_mangle] pub unsafe extern "C" fn wasm_functype_new( From 75ceb0d9e0b8bd97777a0b6443f44b089f0564c2 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 13:56:48 +0100 Subject: [PATCH 03/16] fix(c-api) Fix how `wasm_globaltype_t` is implemented. In `wasm.h`, `wasm_globaltype_t` is implemented with `WASM_DECLARE_TYPE`, so with `WASM_DECLARE_VEC(globaltype, *)`. This `*` means the C struct for the vector is defined: ```c struct wasm_globaltype_vec_t { size_t size; wasm_globaltype_t** data; } ``` The way we implement `wasm_globaltype_vec_t` in Rust is with the `wasm_declare_vec!` macro. And it is wrong. We must use `wasm_declared_boxed_vec!`. --- lib/c-api/src/wasm_c_api/types/global.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/global.rs b/lib/c-api/src/wasm_c_api/types/global.rs index 2195933334c..1b202ad8473 100644 --- a/lib/c-api/src/wasm_c_api/types/global.rs +++ b/lib/c-api/src/wasm_c_api/types/global.rs @@ -46,7 +46,7 @@ impl wasm_globaltype_t { } } -wasm_declare_vec!(globaltype); +wasm_declare_boxed_vec!(globaltype); #[no_mangle] pub unsafe extern "C" fn wasm_globaltype_new( From a3c7a2d75235ea1e606c2432ace6bfbd0041157c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 13:58:26 +0100 Subject: [PATCH 04/16] fix(c-api) Fix how `wasm_memorytype_t` is implemented. In `wasm.h`, `wasm_memorytype_t` is implemented with `WASM_DECLARE_TYPE`, so with `WASM_DECLARE_VEC(memorytype, *)`. This `*` means the C struct for the vector is defined: ```c struct wasm_memorytype_vec_t { size_t size; wasm_memorytype_t** data; } ``` The way we implement `wasm_memorytype_vec_t` in Rust is with the `wasm_declare_vec!` macro. And it is wrong. We must use `wasm_declared_boxed_vec!`. --- lib/c-api/src/wasm_c_api/types/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/memory.rs b/lib/c-api/src/wasm_c_api/types/memory.rs index d38385b88e5..948ff6cf1ec 100644 --- a/lib/c-api/src/wasm_c_api/types/memory.rs +++ b/lib/c-api/src/wasm_c_api/types/memory.rs @@ -48,7 +48,7 @@ impl wasm_memorytype_t { } } -wasm_declare_vec!(memorytype); +wasm_declare_boxed_vec!(memorytype); #[no_mangle] pub unsafe extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box { From a0c34fe850069db5fdc567190044df0f3ae4cbcf Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:00:07 +0100 Subject: [PATCH 05/16] fix(c-api) Fix how `wasm_tabletype_t` is implemented. In `wasm.h`, `wasm_tabletype_t` is implemented with `WASM_DECLARE_TYPE`, so with `WASM_DECLARE_VEC(tabletype, *)`. This `*` means the C struct for the vector is defined: ```c struct wasm_tabletype_vec_t { size_t size; wasm_tabletype_t** data; } ``` The way we implement `wasm_tabletype_vec_t` in Rust is with the `wasm_declare_vec!` macro. And it is wrong. We must use `wasm_declared_boxed_vec!`. --- lib/c-api/src/wasm_c_api/types/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/table.rs b/lib/c-api/src/wasm_c_api/types/table.rs index 31e2525eddd..1f30ad17981 100644 --- a/lib/c-api/src/wasm_c_api/types/table.rs +++ b/lib/c-api/src/wasm_c_api/types/table.rs @@ -53,7 +53,7 @@ impl wasm_tabletype_t { } } -wasm_declare_vec!(tabletype); +wasm_declare_boxed_vec!(tabletype); #[no_mangle] pub unsafe extern "C" fn wasm_tabletype_new( From 4abf6f81da5e6b053ffa132d0c58b4ed4a8612a5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:15:28 +0100 Subject: [PATCH 06/16] fix(c-api) Fix how `wasm_frame_t` is implemented. In `wasm.h`, `wasm_frame_t` is implemented with `WASM_DECLARE_TYPE`, so with `WASM_DECLARE_VEC(frame, *)`. This `*` means the C struct for the vector is defined: ```c struct wasm_frame_vec_t { size_t size; wasm_frame_t** data; } ``` The way we implement `wasm_frame_vec_t` in Rust is with the `wasm_declare_vec!` macro. And it is wrong. We must use `wasm_declared_boxed_vec!`. --- lib/c-api/src/wasm_c_api/types/frame.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs index d926ce977b9..99f3361ab63 100644 --- a/lib/c-api/src/wasm_c_api/types/frame.rs +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -48,4 +48,4 @@ pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize frame.info.module_offset() } -wasm_declare_vec!(frame); +wasm_declare_boxed_vec!(frame); From 43026e651ed0d22f45c228033a39ebec6db259b9 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:17:17 +0100 Subject: [PATCH 07/16] feat(c-api) Implement `From<&[T]> for wasm_$name_vec_t` for boxed vec. --- lib/c-api/src/wasm_c_api/macros.rs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 92dd1590206..07a99b01545 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -42,7 +42,7 @@ int main() { macro_rules! wasm_declare_vec { ($name:ident) => { paste::paste! { - #[doc = "Represents of a vector of `wasm_" $name "_t`. + #[doc = "Represents a vector of `wasm_" $name "_t`. Read the documentation of [`wasm_" $name "_t`] to see more concrete examples. @@ -107,6 +107,7 @@ int main() { .into_boxed_slice(); let data = copied_data.as_mut_ptr(); ::std::mem::forget(copied_data); + Self { size, data, @@ -183,7 +184,9 @@ int main() { macro_rules! wasm_declare_boxed_vec { ($name:ident) => { paste::paste! { - #[doc = "Represents of a vector of [`wasm_" $name "_t`]."] + #[doc = "Represents a vector of `wasm_" $name "_t`. + +Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."] #[derive(Debug)] #[repr(C)] pub struct [] { @@ -206,6 +209,27 @@ macro_rules! wasm_declare_boxed_vec { } } + impl<'a, T: Into<[]> + Clone> From<&'a [T]> for [] { + fn from(other: &'a [T]) -> Self { + let size = other.len(); + let mut copied_data = other + .iter() + .cloned() + .map(Into::into) + .map(Box::new) + .map(Box::into_raw) + .collect::]>>() + .into_boxed_slice(); + let data = copied_data.as_mut_ptr(); + ::std::mem::forget(copied_data); + + Self { + size, + data, + } + } + } + // TODO: do this properly impl [] { pub unsafe fn into_slice(&self) -> Option<&[Box<[]>]>{ From 940dea72e7e78ea8f4abf167e94ae6d5c3ac4c46 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:17:50 +0100 Subject: [PATCH 08/16] feat(c-api) Simplify code by using new conversion implementations. --- lib/c-api/src/wasm_c_api/types/function.rs | 45 ++-------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index cf8cfeaa347..2d8a5d163d7 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -1,7 +1,4 @@ -use super::{ - wasm_externtype_t, wasm_valtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType, -}; -use std::mem; +use super::{wasm_externtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType}; use wasmer::{ExternType, FunctionType, ValType}; #[derive(Debug)] @@ -13,44 +10,8 @@ pub(crate) struct WasmFunctionType { impl WasmFunctionType { pub(crate) fn new(function_type: FunctionType) -> Self { - let params = { - let mut valtypes = function_type - .params() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - let valtypes_vec = Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - }); - - mem::forget(valtypes); - - valtypes_vec - }; - let results = { - let mut valtypes = function_type - .results() - .iter() - .cloned() - .map(Into::into) - .map(Box::new) - .map(Box::into_raw) - .collect::>(); - - let valtypes_vec = Box::new(wasm_valtype_vec_t { - size: valtypes.len(), - data: valtypes.as_mut_ptr(), - }); - - mem::forget(valtypes); - - valtypes_vec - }; + let params: Box = Box::new(function_type.params().into()); + let results: Box = Box::new(function_type.results().into()); Self { function_type, From 8aa08225cd5575bb6a590bdf11dcfd0ceb772203 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:55:29 +0100 Subject: [PATCH 09/16] feat(c-api) `wasm_$name_vec_delete` checks the vec is initialized. In case of a boxed vector, `wasm_$name_vec_delete` now checks that the vec is correctly initialized (by checking the first item only) because transmuting `Vec<*mut T>` to `Vec>`, otherwise it will crash. --- lib/c-api/src/wasm_c_api/macros.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 07a99b01545..8132f5cc5c2 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -274,7 +274,14 @@ Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."] let vec = &mut *ptr; if !vec.data.is_null() { let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); - let _data: Vec]>> = ::std::mem::transmute(data); + + // If the vector has been initialized (we check + // only the first item), we can transmute items to + // `Box`es. + if vec.size > 0 && !data[0].is_null() { + let _data: Vec]>> = ::std::mem::transmute(data); + } + vec.data = ::std::ptr::null_mut(); vec.size = 0; } @@ -299,7 +306,6 @@ macro_rules! wasm_declare_ref_base { } // TODO: finish this... - } }; } From 96169de8f0e6f4f693a8c46dfce493df10eca7ac Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 14:57:07 +0100 Subject: [PATCH 10/16] test+doc(c-api) Improve test coverage for the `macros` module, and improve doc. --- lib/c-api/src/wasm_c_api/macros.rs | 82 ++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 8132f5cc5c2..49989acd708 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -138,31 +138,68 @@ int main() { } // TODO: investigate possible memory leak on `init` (owned pointer) - #[doc = "Creates a new vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new vector of [`wasm_" $name "_t`]. + +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *mut []) { let mut bytes: Vec<[]> = Vec::with_capacity(length); + for i in 0..length { bytes.push(::std::ptr::read(init.add(i))); } + let pointer = bytes.as_mut_ptr(); debug_assert!(bytes.len() == bytes.capacity()); + (*out).data = pointer; (*out).size = length; ::std::mem::forget(bytes); } - #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_uninitialized(&vector, 3); + + // Check that it contains 3 items. + assert(vector.size == 3); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<[]> = Vec::with_capacity(length); let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(bytes); } - #[doc = "Deletes a vector of [`wasm_" $name "_t`]."] + #[doc = "Deletes a vector of [`wasm_" $name "_t`]. + +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] pub unsafe extern "C" fn [](ptr: Option<&mut []>) { if let Some(vec) = ptr { @@ -248,30 +285,65 @@ Read the documentation of [`wasm_" $name "_t`] to see more concrete examples."] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize, init: *const *mut []) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + for i in 0..length { bytes.push(*init.add(i)); } + let pointer = bytes.as_mut_ptr(); debug_assert!(bytes.len() == bytes.capacity()); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(bytes); } - #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]."] + #[doc = "Creates a new uninitialized vector of [`wasm_" $name "_t`]. + +# Example + +```rust +# use inline_c::assert_c; +# fn main() { +# (assert_c! { +# #include \"tests/wasmer_wasm.h\" +# +int main() { + // Creates an empty vector of `wasm_" $name "_t`. + wasm_" $name "_vec_t vector; + wasm_" $name "_vec_new_uninitialized(&vector, 3); + + // Check that it contains 3 items. + assert(vector.size == 3); + + // Free it. + wasm_" $name "_vec_delete(&vector); +} +# }) +# .success(); +# } +```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { let mut bytes: Vec<*mut []> = Vec::with_capacity(length); let pointer = bytes.as_mut_ptr(); + (*out).data = pointer; (*out).size = length; + ::std::mem::forget(bytes); } - #[doc = "Deletes a vector of [`wasm_" $name "_t`]."] + #[doc = "Deletes a vector of [`wasm_" $name "_t`]. + +# Example + +See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] pub unsafe extern "C" fn [](ptr: *mut []) { let vec = &mut *ptr; + if !vec.data.is_null() { let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); From 2853bd436df020df70a6ec4af538d7d177fb8ea1 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 17 Dec 2020 15:10:36 +0100 Subject: [PATCH 11/16] doc(changelog) Add #1949. --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fda945847cf..6a5c7b6b563 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ ### Fixed +- [#1949](https://github.com/wasmerio/wasmer/pull/1949) `wasm__vec_delete` functions no longer crash when the given vector is uninitialized, in the Wasmer C API +- [#1949](https://github.com/wasmerio/wasmer/pull/1949) The `wasm_frame_vec_t`, `wasm_functype_vec_t`, `wasm_globaltype_vec_t`, `wasm_memorytype_vec_t`, and `wasm_tabletype_vec_t` are now boxed vectors in the Wasmer C API + ## 1.0.0-beta2 - 2020-12-16 ### Added From 51fe219efbb260193753441a0a42c704ea9cfd2d Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Dec 2020 10:45:57 +0100 Subject: [PATCH 12/16] feat(c-api) `wasm_$name_vec_delete` for boxed vec now takes an `Option<&mut T>`. This was already the case for regular vec. This patch applies the same pattern for boxed vec. See https://github.com/wasmerio/wasmer/commit/deec77d2df094ab6f9b3c9890c1ac9e33c4d44fb. --- lib/c-api/src/wasm_c_api/macros.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 49989acd708..0feab8cd33a 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -341,21 +341,21 @@ int main() { See the [`wasm_" $name "_vec_t`] type to get an example."] #[no_mangle] - pub unsafe extern "C" fn [](ptr: *mut []) { - let vec = &mut *ptr; + pub unsafe extern "C" fn [](ptr: Option<&mut []>) { + if let Some(vec) = ptr { + if !vec.data.is_null() { + let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); - if !vec.data.is_null() { - let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); + // If the vector has been initialized (we check + // only the first item), we can transmute items to + // `Box`es. + if vec.size > 0 && !data[0].is_null() { + let _data: Vec]>> = ::std::mem::transmute(data); + } - // If the vector has been initialized (we check - // only the first item), we can transmute items to - // `Box`es. - if vec.size > 0 && !data[0].is_null() { - let _data: Vec]>> = ::std::mem::transmute(data); + vec.data = ::std::ptr::null_mut(); + vec.size = 0; } - - vec.data = ::std::ptr::null_mut(); - vec.size = 0; } } } From a68a1e67f414bcbe9f8c4bb1187bef2dacd79764 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Dec 2020 11:40:27 +0100 Subject: [PATCH 13/16] feat(c-api) Transmute boxed vecs to `Vec>>` when deleting. It's a safer way to handle partially uninitialized boxed vector, since it protects against based deletion for every item. --- lib/c-api/src/wasm_c_api/macros.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 0feab8cd33a..8702becdb3b 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -345,13 +345,7 @@ See the [`wasm_" $name "_vec_t`] type to get an example."] if let Some(vec) = ptr { if !vec.data.is_null() { let data: Vec<*mut []> = Vec::from_raw_parts(vec.data, vec.size, vec.size); - - // If the vector has been initialized (we check - // only the first item), we can transmute items to - // `Box`es. - if vec.size > 0 && !data[0].is_null() { - let _data: Vec]>> = ::std::mem::transmute(data); - } + let _data: Vec]>>> = ::std::mem::transmute(data); vec.data = ::std::ptr::null_mut(); vec.size = 0; From 40fa9c08c76b9bc0b4b3d1a1261cb163ad6e8f9b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Dec 2020 11:42:34 +0100 Subject: [PATCH 14/16] fix(c-api) UPdate `wasm_functype_new` according to previous commit. --- lib/c-api/src/wasm_c_api/types/function.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 2d8a5d163d7..10df28a2901 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -1,4 +1,5 @@ use super::{wasm_externtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType}; +use std::mem; use wasmer::{ExternType, FunctionType, ValType}; #[derive(Debug)] @@ -58,8 +59,8 @@ pub unsafe extern "C" fn wasm_functype_new( params: Option>, results: Option>, ) -> Option> { - let params = params?; - let results = results?; + let mut params = params?; + let mut results = results?; let params_as_valtype: Vec = params .into_slice()? @@ -72,8 +73,11 @@ pub unsafe extern "C" fn wasm_functype_new( .map(|val| val.as_ref().into()) .collect::>(); - wasm_valtype_vec_delete(Box::into_raw(params)); - wasm_valtype_vec_delete(Box::into_raw(results)); + wasm_valtype_vec_delete(Some(params.as_mut())); + wasm_valtype_vec_delete(Some(results.as_mut())); + + mem::forget(params); + mem::forget(results); Some(Box::new(wasm_functype_t::new(FunctionType::new( params_as_valtype, From 2ca30fe6348d0daefa00e7dfe03cdbfe584e1aad Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Dec 2020 11:47:04 +0100 Subject: [PATCH 15/16] fix(c-api) Ensure that uninitialized boxed vec are zeroed. This patch updates how `wasm_$name_vec_new_uninitialized` creates the vector. The vector is now fully allocated with `null` pointer for each item, instead of having an empty vector with the initial capacity set to `length`. That way, we are sure the vector is zeroed correctly. --- lib/c-api/src/wasm_c_api/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 8702becdb3b..cc5a520d2ec 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -326,7 +326,7 @@ int main() { ```"] #[no_mangle] pub unsafe extern "C" fn [](out: *mut [], length: usize) { - let mut bytes: Vec<*mut []> = Vec::with_capacity(length); + let mut bytes: Vec<*mut []> = vec![::std::ptr::null_mut(); length]; let pointer = bytes.as_mut_ptr(); (*out).data = pointer; From b9afb6e95659432402b8c535e159f735b0b2e08a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 18 Dec 2020 17:35:21 +0100 Subject: [PATCH 16/16] fix(c-api) Remove `Box` from `wasm_functype_new`. --- lib/c-api/src/wasm_c_api/types/function.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index 10df28a2901..a5318dbef45 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -1,5 +1,4 @@ use super::{wasm_externtype_t, wasm_valtype_vec_delete, wasm_valtype_vec_t, WasmExternType}; -use std::mem; use wasmer::{ExternType, FunctionType, ValType}; #[derive(Debug)] @@ -56,11 +55,11 @@ wasm_declare_boxed_vec!(functype); #[no_mangle] pub unsafe extern "C" fn wasm_functype_new( - params: Option>, - results: Option>, + params: Option<&mut wasm_valtype_vec_t>, + results: Option<&mut wasm_valtype_vec_t>, ) -> Option> { - let mut params = params?; - let mut results = results?; + let params = params?; + let results = results?; let params_as_valtype: Vec = params .into_slice()? @@ -73,11 +72,8 @@ pub unsafe extern "C" fn wasm_functype_new( .map(|val| val.as_ref().into()) .collect::>(); - wasm_valtype_vec_delete(Some(params.as_mut())); - wasm_valtype_vec_delete(Some(results.as_mut())); - - mem::forget(params); - mem::forget(results); + wasm_valtype_vec_delete(Some(params)); + wasm_valtype_vec_delete(Some(results)); Some(Box::new(wasm_functype_t::new(FunctionType::new( params_as_valtype,