Fix memory leaks in extern conversion functions in C API. (#395)
This fixes the memory leaks in the following functions which should not be returning "owned" pointers: * `wasm_extern_as_func` * `wasm_func_as_extern` * `wasm_extern_as_global` * `wasm_global_as_extern` * `wasm_extern_as_memory` * `wasm_extern_as_table` Additionally, this commit implements the `wasm_memory_as_extern` and `wasm_table_as_extern` functions. Fixes #394.
This commit is contained in:
committed by
Yury Delendik
parent
e1b9c01d94
commit
cb38b48156
@@ -343,6 +343,7 @@ pub struct wasm_shared_module_t {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_func_t {
|
pub struct wasm_func_t {
|
||||||
func: HostRef<Func>,
|
func: HostRef<Func>,
|
||||||
|
ext: Option<Box<wasm_extern_t>>,
|
||||||
}
|
}
|
||||||
pub type wasm_func_callback_t = ::std::option::Option<
|
pub type wasm_func_callback_t = ::std::option::Option<
|
||||||
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
|
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t,
|
||||||
@@ -358,23 +359,36 @@ pub type wasm_func_callback_with_env_t = ::std::option::Option<
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_global_t {
|
pub struct wasm_global_t {
|
||||||
global: HostRef<Global>,
|
global: HostRef<Global>,
|
||||||
|
ext: Option<Box<wasm_extern_t>>,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_table_t {
|
pub struct wasm_table_t {
|
||||||
table: HostRef<Table>,
|
table: HostRef<Table>,
|
||||||
|
ext: Option<Box<wasm_extern_t>>,
|
||||||
}
|
}
|
||||||
pub type wasm_table_size_t = u32;
|
pub type wasm_table_size_t = u32;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_memory_t {
|
pub struct wasm_memory_t {
|
||||||
memory: HostRef<Memory>,
|
memory: HostRef<Memory>,
|
||||||
|
ext: Option<Box<wasm_extern_t>>,
|
||||||
}
|
}
|
||||||
pub type wasm_memory_pages_t = u32;
|
pub type wasm_memory_pages_t = u32;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_extern_t {
|
pub struct wasm_extern_t {
|
||||||
ext: Extern,
|
ext: Extern,
|
||||||
|
cache: wasm_extern_t_type_cache,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum wasm_extern_t_type_cache {
|
||||||
|
Empty,
|
||||||
|
Func(wasm_func_t),
|
||||||
|
Global(wasm_global_t),
|
||||||
|
Memory(wasm_memory_t),
|
||||||
|
Table(wasm_table_t),
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
|
declare_vec!(wasm_extern_vec_t, *mut wasm_extern_t);
|
||||||
@@ -404,13 +418,17 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
|
pub unsafe extern "C" fn wasm_extern_as_func(e: *mut wasm_extern_t) -> *mut wasm_func_t {
|
||||||
let func = if let Some(f) = (*e).ext.func() {
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
||||||
f.clone()
|
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t {
|
||||||
} else {
|
func: (*e).ext.func().unwrap().clone(),
|
||||||
return ptr::null_mut();
|
ext: None,
|
||||||
};
|
});
|
||||||
let func = Box::new(wasm_func_t { func });
|
}
|
||||||
Box::into_raw(func)
|
|
||||||
|
match &mut (*e).cache {
|
||||||
|
wasm_extern_t_type_cache::Func(f) => f,
|
||||||
|
_ => panic!("wasm_extern_as_func"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -420,9 +438,17 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_func_as_extern(f: *mut wasm_func_t) -> *mut wasm_extern_t {
|
||||||
let ext = Extern::Func((*f).func.clone());
|
if (*f).ext.is_none() {
|
||||||
let ext = Box::new(wasm_extern_t { ext });
|
(*f).ext = Some(Box::new(wasm_extern_t {
|
||||||
Box::into_raw(ext)
|
ext: Extern::Func((*f).func.clone()),
|
||||||
|
cache: wasm_extern_t_type_cache::Empty,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut (*f).ext {
|
||||||
|
Some(e) => e.as_mut(),
|
||||||
|
_ => panic!("wasm_func_as_extern"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -588,6 +614,7 @@ pub unsafe extern "C" fn wasm_func_new(
|
|||||||
let callback = Rc::new(callback);
|
let callback = Rc::new(callback);
|
||||||
let func = Box::new(wasm_func_t {
|
let func = Box::new(wasm_func_t {
|
||||||
func: HostRef::new(Func::new(store, ty, callback)),
|
func: HostRef::new(Func::new(store, ty, callback)),
|
||||||
|
ext: None,
|
||||||
});
|
});
|
||||||
Box::into_raw(func)
|
Box::into_raw(func)
|
||||||
}
|
}
|
||||||
@@ -675,7 +702,10 @@ pub unsafe extern "C" fn wasm_instance_exports(
|
|||||||
let exports = instance.exports();
|
let exports = instance.exports();
|
||||||
let mut buffer = Vec::with_capacity(exports.len());
|
let mut buffer = Vec::with_capacity(exports.len());
|
||||||
for e in exports.iter() {
|
for e in exports.iter() {
|
||||||
let ext = Box::new(wasm_extern_t { ext: e.clone() });
|
let ext = Box::new(wasm_extern_t {
|
||||||
|
ext: e.clone(),
|
||||||
|
cache: wasm_extern_t_type_cache::Empty,
|
||||||
|
});
|
||||||
buffer.push(Box::into_raw(ext));
|
buffer.push(Box::into_raw(ext));
|
||||||
}
|
}
|
||||||
(*out).set_buffer(buffer);
|
(*out).set_buffer(buffer);
|
||||||
@@ -783,6 +813,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
|
|||||||
});
|
});
|
||||||
let func = Box::new(wasm_func_t {
|
let func = Box::new(wasm_func_t {
|
||||||
func: HostRef::new(Func::new(store, ty, callback)),
|
func: HostRef::new(Func::new(store, ty, callback)),
|
||||||
|
ext: None,
|
||||||
});
|
});
|
||||||
Box::into_raw(func)
|
Box::into_raw(func)
|
||||||
}
|
}
|
||||||
@@ -1238,20 +1269,32 @@ pub unsafe extern "C" fn wasm_valtype_kind(vt: *const wasm_valtype_t) -> wasm_va
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
|
pub unsafe extern "C" fn wasm_extern_as_global(e: *mut wasm_extern_t) -> *mut wasm_global_t {
|
||||||
let global = if let Some(g) = (*e).ext.global() {
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
||||||
g.clone()
|
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t {
|
||||||
} else {
|
global: (*e).ext.global().unwrap().clone(),
|
||||||
return ptr::null_mut();
|
ext: None,
|
||||||
};
|
});
|
||||||
let g = Box::new(wasm_global_t { global });
|
}
|
||||||
Box::into_raw(g)
|
|
||||||
|
match &mut (*e).cache {
|
||||||
|
wasm_extern_t_type_cache::Global(g) => g,
|
||||||
|
_ => panic!("wasm_extern_as_global"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
|
||||||
let ext = (*g).global.clone().into();
|
if (*g).ext.is_none() {
|
||||||
let ext = Box::new(wasm_extern_t { ext });
|
(*g).ext = Some(Box::new(wasm_extern_t {
|
||||||
Box::into_raw(ext)
|
ext: Extern::Global((*g).global.clone()),
|
||||||
|
cache: wasm_extern_t_type_cache::Empty,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut (*g).ext {
|
||||||
|
Some(e) => e.as_mut(),
|
||||||
|
_ => panic!("wasm_global_as_extern"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1283,7 +1326,7 @@ pub unsafe extern "C" fn wasm_global_new(
|
|||||||
(*gt).globaltype.clone(),
|
(*gt).globaltype.clone(),
|
||||||
(*val).val(),
|
(*val).val(),
|
||||||
));
|
));
|
||||||
let g = Box::new(wasm_global_t { global });
|
let g = Box::new(wasm_global_t { global, ext: None });
|
||||||
Box::into_raw(g)
|
Box::into_raw(g)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,13 +1367,32 @@ pub unsafe extern "C" fn wasm_globaltype_new(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
|
pub unsafe extern "C" fn wasm_extern_as_memory(e: *mut wasm_extern_t) -> *mut wasm_memory_t {
|
||||||
let memory = if let Some(m) = (*e).ext.memory() {
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
||||||
m.clone()
|
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t {
|
||||||
} else {
|
memory: (*e).ext.memory().unwrap().clone(),
|
||||||
return ptr::null_mut();
|
ext: None,
|
||||||
};
|
});
|
||||||
let g = Box::new(wasm_memory_t { memory });
|
}
|
||||||
Box::into_raw(g)
|
|
||||||
|
match &mut (*e).cache {
|
||||||
|
wasm_extern_t_type_cache::Memory(m) => m,
|
||||||
|
_ => panic!("wasm_extern_as_memory"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_memory_as_extern(m: *mut wasm_memory_t) -> *mut wasm_extern_t {
|
||||||
|
if (*m).ext.is_none() {
|
||||||
|
(*m).ext = Some(Box::new(wasm_extern_t {
|
||||||
|
ext: Extern::Memory((*m).memory.clone()),
|
||||||
|
cache: wasm_extern_t_type_cache::Empty,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut (*m).ext {
|
||||||
|
Some(e) => e.as_mut(),
|
||||||
|
_ => panic!("wasm_global_as_extern"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1383,7 +1445,7 @@ pub unsafe extern "C" fn wasm_memory_new(
|
|||||||
(*store).store.clone(),
|
(*store).store.clone(),
|
||||||
(*mt).memorytype.clone(),
|
(*mt).memorytype.clone(),
|
||||||
));
|
));
|
||||||
let m = Box::new(wasm_memory_t { memory });
|
let m = Box::new(wasm_memory_t { memory, ext: None });
|
||||||
Box::into_raw(m)
|
Box::into_raw(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1406,13 +1468,32 @@ pub unsafe extern "C" fn wasm_memorytype_new(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
||||||
let table = if let Some(t) = (*e).ext.table() {
|
if let wasm_extern_t_type_cache::Empty = (*e).cache {
|
||||||
t.clone()
|
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t {
|
||||||
} else {
|
table: (*e).ext.table().unwrap().clone(),
|
||||||
return ptr::null_mut();
|
ext: None,
|
||||||
};
|
});
|
||||||
let t = Box::new(wasm_table_t { table });
|
}
|
||||||
Box::into_raw(t)
|
|
||||||
|
match &mut (*e).cache {
|
||||||
|
wasm_extern_t_type_cache::Table(t) => t,
|
||||||
|
_ => panic!("wasm_extern_as_table"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_as_extern(t: *mut wasm_table_t) -> *mut wasm_extern_t {
|
||||||
|
if (*t).ext.is_none() {
|
||||||
|
(*t).ext = Some(Box::new(wasm_extern_t {
|
||||||
|
ext: Extern::Table((*t).table.clone()),
|
||||||
|
cache: wasm_extern_t_type_cache::Empty,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
match &mut (*t).ext {
|
||||||
|
Some(e) => e.as_mut(),
|
||||||
|
_ => panic!("wasm_table_as_extern"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -1456,6 +1537,7 @@ pub unsafe extern "C" fn wasm_table_new(
|
|||||||
(*tt).tabletype.clone(),
|
(*tt).tabletype.clone(),
|
||||||
init,
|
init,
|
||||||
)),
|
)),
|
||||||
|
ext: None,
|
||||||
});
|
});
|
||||||
Box::into_raw(t)
|
Box::into_raw(t)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user