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, + } } }