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:
Peter Huene
2019-10-02 05:54:36 -07:00
committed by Yury Delendik
parent e1b9c01d94
commit cb38b48156

View File

@@ -343,6 +343,7 @@ pub struct wasm_shared_module_t {
#[derive(Clone)]
pub struct wasm_func_t {
func: HostRef<Func>,
ext: Option<Box<wasm_extern_t>>,
}
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,
@@ -358,23 +359,36 @@ pub type wasm_func_callback_with_env_t = ::std::option::Option<
#[derive(Clone)]
pub struct wasm_global_t {
global: HostRef<Global>,
ext: Option<Box<wasm_extern_t>>,
}
#[repr(C)]
#[derive(Clone)]
pub struct wasm_table_t {
table: HostRef<Table>,
ext: Option<Box<wasm_extern_t>>,
}
pub type wasm_table_size_t = u32;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_memory_t {
memory: HostRef<Memory>,
ext: Option<Box<wasm_extern_t>>,
}
pub type wasm_memory_pages_t = u32;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_extern_t {
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);
@@ -404,13 +418,17 @@ pub unsafe extern "C" fn wasm_engine_new() -> *mut wasm_engine_t {
#[no_mangle]
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() {
f.clone()
} else {
return ptr::null_mut();
};
let func = Box::new(wasm_func_t { func });
Box::into_raw(func)
if let wasm_extern_t_type_cache::Empty = (*e).cache {
(*e).cache = wasm_extern_t_type_cache::Func(wasm_func_t {
func: (*e).ext.func().unwrap().clone(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Func(f) => f,
_ => panic!("wasm_extern_as_func"),
}
}
#[no_mangle]
@@ -420,9 +438,17 @@ pub unsafe extern "C" fn wasm_extern_vec_delete(v: *mut wasm_extern_vec_t) {
#[no_mangle]
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());
let ext = Box::new(wasm_extern_t { ext });
Box::into_raw(ext)
if (*f).ext.is_none() {
(*f).ext = Some(Box::new(wasm_extern_t {
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]
@@ -588,6 +614,7 @@ pub unsafe extern "C" fn wasm_func_new(
let callback = Rc::new(callback);
let func = Box::new(wasm_func_t {
func: HostRef::new(Func::new(store, ty, callback)),
ext: None,
});
Box::into_raw(func)
}
@@ -675,7 +702,10 @@ pub unsafe extern "C" fn wasm_instance_exports(
let exports = instance.exports();
let mut buffer = Vec::with_capacity(exports.len());
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));
}
(*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 {
func: HostRef::new(Func::new(store, ty, callback)),
ext: None,
});
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]
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() {
g.clone()
} else {
return ptr::null_mut();
};
let g = Box::new(wasm_global_t { global });
Box::into_raw(g)
if let wasm_extern_t_type_cache::Empty = (*e).cache {
(*e).cache = wasm_extern_t_type_cache::Global(wasm_global_t {
global: (*e).ext.global().unwrap().clone(),
ext: None,
});
}
match &mut (*e).cache {
wasm_extern_t_type_cache::Global(g) => g,
_ => panic!("wasm_extern_as_global"),
}
}
#[no_mangle]
pub unsafe extern "C" fn wasm_global_as_extern(g: *mut wasm_global_t) -> *mut wasm_extern_t {
let ext = (*g).global.clone().into();
let ext = Box::new(wasm_extern_t { ext });
Box::into_raw(ext)
if (*g).ext.is_none() {
(*g).ext = Some(Box::new(wasm_extern_t {
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]
@@ -1283,7 +1326,7 @@ pub unsafe extern "C" fn wasm_global_new(
(*gt).globaltype.clone(),
(*val).val(),
));
let g = Box::new(wasm_global_t { global });
let g = Box::new(wasm_global_t { global, ext: None });
Box::into_raw(g)
}
@@ -1324,13 +1367,32 @@ pub unsafe extern "C" fn wasm_globaltype_new(
#[no_mangle]
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() {
m.clone()
} else {
return ptr::null_mut();
};
let g = Box::new(wasm_memory_t { memory });
Box::into_raw(g)
if let wasm_extern_t_type_cache::Empty = (*e).cache {
(*e).cache = wasm_extern_t_type_cache::Memory(wasm_memory_t {
memory: (*e).ext.memory().unwrap().clone(),
ext: None,
});
}
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]
@@ -1383,7 +1445,7 @@ pub unsafe extern "C" fn wasm_memory_new(
(*store).store.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)
}
@@ -1406,13 +1468,32 @@ pub unsafe extern "C" fn wasm_memorytype_new(
#[no_mangle]
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() {
t.clone()
} else {
return ptr::null_mut();
};
let t = Box::new(wasm_table_t { table });
Box::into_raw(t)
if let wasm_extern_t_type_cache::Empty = (*e).cache {
(*e).cache = wasm_extern_t_type_cache::Table(wasm_table_t {
table: (*e).ext.table().unwrap().clone(),
ext: None,
});
}
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]
@@ -1456,6 +1537,7 @@ pub unsafe extern "C" fn wasm_table_new(
(*tt).tabletype.clone(),
init,
)),
ext: None,
});
Box::into_raw(t)
}