From fdb077236a6847a360b6e4cefe845682548f04e0 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 6 Oct 2020 22:19:50 +0200 Subject: [PATCH 1/3] feat(c-api) Implement `wasm_exporttype_delete`. --- lib/c-api/src/wasm_c_api/types/export.rs | 3 +++ 1 file changed, 3 insertions(+) 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 1a9c0301183..919e0927164 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -30,6 +30,9 @@ pub extern "C" fn wasm_exporttype_type( unsafe { et.extern_type.as_ref() } } +#[no_mangle] +pub extern "C" fn wasm_exporttype_delete(_exporttype: Option>) {} + impl From for wasm_exporttype_t { fn from(other: ExportType) -> Self { (&other).into() From f24a34b6cf62d5ede45445065b432b4dff8d33df Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 13:38:01 +0200 Subject: [PATCH 2/3] feat(c-api) Implement `Drop` for `wasm_exporttype_t`. `wasm_exporttype_t` has 2 fields: `name` and `extern_type`. Both are of kind `NonNull`. When `wasm_exporttype_t` is dropped, nor `name` nor `extern_type` are going to be dropped. To avoid leaking data, this patch adds a new field: `owns_fields`: * When `wasm_exporttype_t` is built from `wasm_exportype_new`, this field is set to `false` because `name` and `extern_type` are received by pointer, and its the responsibility of the caller to free them, * When `wasm_exporttype_t` is built from the `From<&ExportType>` implementation, _we_ create `name` and `extern_type` to then leak them. In this case, it is safe to reconstruct proper `Box`es to finally drop them. --- lib/c-api/src/wasm_c_api/types/export.rs | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) 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 919e0927164..cd05ff6c63c 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -6,6 +6,7 @@ use wasmer::ExportType; pub struct wasm_exporttype_t { name: NonNull, extern_type: NonNull, + owns_fields: bool, } wasm_declare_boxed_vec!(exporttype); @@ -15,7 +16,11 @@ pub extern "C" fn wasm_exporttype_new( name: NonNull, extern_type: NonNull, ) -> Box { - Box::new(wasm_exporttype_t { name, extern_type }) + Box::new(wasm_exporttype_t { + name, + extern_type, + owns_fields: false, + }) } #[no_mangle] @@ -33,6 +38,20 @@ pub extern "C" fn wasm_exporttype_type( #[no_mangle] pub extern "C" fn wasm_exporttype_delete(_exporttype: Option>) {} +impl Drop for wasm_exporttype_t { + fn drop(&mut self) { + if self.owns_fields { + // SAFETY: `owns_fields` is set to `true` only in + // `wasm_exporttype_t.from(&ExportType)`, where the data + // are leaked properly and won't be freed somewhere else. + unsafe { + let _ = Box::from_raw(self.name.as_ptr()); + let _ = Box::from_raw(self.extern_type.as_ptr()); + } + } + } +} + impl From for wasm_exporttype_t { fn from(other: ExportType) -> Self { (&other).into() @@ -59,6 +78,10 @@ impl From<&ExportType> for wasm_exporttype_t { unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) } }; - wasm_exporttype_t { name, extern_type } + wasm_exporttype_t { + name, + extern_type, + owns_fields: true, + } } } From 3ebff7426338fae1c96a1fe834ce8672417d6644 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 8 Oct 2020 13:43:59 +0200 Subject: [PATCH 3/3] doc(c-api) Update inline API documentation. --- lib/c-api/src/wasm_c_api/types/export.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 cd05ff6c63c..1476ecb5b23 100644 --- a/lib/c-api/src/wasm_c_api/types/export.rs +++ b/lib/c-api/src/wasm_c_api/types/export.rs @@ -6,6 +6,9 @@ use wasmer::ExportType; pub struct wasm_exporttype_t { name: NonNull, extern_type: NonNull, + + /// If `true`, `name` and `extern_type` will be dropped by + /// `wasm_exporttype_t::drop`. owns_fields: bool, } @@ -42,7 +45,7 @@ impl Drop for wasm_exporttype_t { fn drop(&mut self) { if self.owns_fields { // SAFETY: `owns_fields` is set to `true` only in - // `wasm_exporttype_t.from(&ExportType)`, where the data + // `wasm_exporttype_t::from(&ExportType)`, where the data // are leaked properly and won't be freed somewhere else. unsafe { let _ = Box::from_raw(self.name.as_ptr());