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..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,10 @@ 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, } wasm_declare_boxed_vec!(exporttype); @@ -15,7 +19,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] @@ -30,6 +38,23 @@ 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 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() @@ -56,6 +81,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, + } } }