From ff4cb6d412ae5dc2b729be414f199346d0e6db64 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 5 Oct 2020 14:49:23 +0200 Subject: [PATCH 1/2] feat(c-api) Implement `wasm_module_validate`. --- lib/c-api/src/wasm_c_api/module.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 627f932e471..a1e49ebc682 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -3,6 +3,7 @@ use super::types::{ wasm_byte_vec_t, wasm_exporttype_t, wasm_exporttype_vec_t, wasm_importtype_t, wasm_importtype_vec_t, }; +use crate::error::update_last_error; use std::ptr::NonNull; use std::slice; use std::sync::Arc; @@ -32,6 +33,30 @@ pub unsafe extern "C" fn wasm_module_new( #[no_mangle] pub unsafe extern "C" fn wasm_module_delete(_module: Option>) {} +#[no_mangle] +pub unsafe extern "C" fn wasm_module_validate( + store_ptr: Option>, + bytes: &wasm_byte_vec_t, +) -> bool { + // TODO: review lifetime of byte slice. + let wasm_byte_slice: &[u8] = slice::from_raw_parts(bytes.data, bytes.size); + + if store_ptr.is_none() { + return false; + } + + let store_ptr = store_ptr.unwrap().cast::(); + let store = store_ptr.as_ref(); + + if let Err(error) = Module::validate(store, wasm_byte_slice) { + update_last_error(error); + + false + } else { + true + } +} + #[no_mangle] pub unsafe extern "C" fn wasm_module_exports( module: &wasm_module_t, From 3edcc896989180a2f6f7543fe588adb48e9420e3 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Mon, 5 Oct 2020 21:16:43 +0200 Subject: [PATCH 2/2] feat(c-api) Redefine `wasm_store_t`. `wasm_store_t` is now a proper struct (rather than an opaque type) of kind: ```rs struct wasm_store_t { inner: Store } ``` The rest of the patch updates the code accordingly. --- .../src/wasm_c_api/externals/function.rs | 21 +++++++-------- lib/c-api/src/wasm_c_api/externals/global.rs | 8 +++--- lib/c-api/src/wasm_c_api/externals/memory.rs | 9 +++---- lib/c-api/src/wasm_c_api/externals/table.rs | 10 +++---- lib/c-api/src/wasm_c_api/instance.rs | 3 +-- lib/c-api/src/wasm_c_api/module.rs | 27 ++++++------------- lib/c-api/src/wasm_c_api/store.rs | 19 +++++-------- lib/c-api/src/wasm_c_api/wasi/mod.rs | 10 +++---- 8 files changed, 38 insertions(+), 69 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index ee351d955e6..b64f52d87bf 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -4,9 +4,8 @@ use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t}; use std::convert::TryInto; use std::ffi::c_void; -use std::ptr::NonNull; use std::sync::Arc; -use wasmer::{Function, Instance, RuntimeError, Store, Val}; +use wasmer::{Function, Instance, RuntimeError, Val}; #[allow(non_camel_case_types)] pub struct wasm_func_t { @@ -31,13 +30,11 @@ pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void); #[no_mangle] pub unsafe extern "C" fn wasm_func_new( - store: Option>, + store: &wasm_store_t, ft: &wasm_functype_t, callback: wasm_func_callback_t, ) -> Option> { // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); let func_sig = ft.sig(); let num_rets = func_sig.results().len(); let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { @@ -68,24 +65,23 @@ pub unsafe extern "C" fn wasm_func_new( .expect("Result conversion failed"); Ok(processed_results) }; - let f = Function::new(store, &func_sig, inner_callback); + let function = Function::new(&store.inner, &func_sig, inner_callback); + Some(Box::new(wasm_func_t { instance: None, - inner: f, + inner: function, })) } #[no_mangle] pub unsafe extern "C" fn wasm_func_new_with_env( - store: Option>, + store: &wasm_store_t, ft: &wasm_functype_t, callback: wasm_func_callback_with_env_t, env: *mut c_void, finalizer: wasm_env_finalizer_t, ) -> Option> { // TODO: handle null pointers? - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); let func_sig = ft.sig(); let num_rets = func_sig.results().len(); let inner_callback = @@ -114,10 +110,11 @@ pub unsafe extern "C" fn wasm_func_new_with_env( .expect("Result conversion failed"); Ok(processed_results) }; - let f = Function::new_with_env(store, &func_sig, env, inner_callback); + let function = Function::new_with_env(&store.inner, &func_sig, env, inner_callback); + Some(Box::new(wasm_func_t { instance: None, - inner: f, + inner: function, })) } diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 92c1ed1e465..aa04bf6f6e7 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -2,8 +2,7 @@ use super::super::store::wasm_store_t; use super::super::types::wasm_globaltype_t; use super::super::value::wasm_val_t; use std::convert::TryInto; -use std::ptr::NonNull; -use wasmer::{Global, Store, Val}; +use wasmer::{Global, Val}; #[allow(non_camel_case_types)] pub struct wasm_global_t { @@ -13,14 +12,13 @@ pub struct wasm_global_t { #[no_mangle] pub unsafe extern "C" fn wasm_global_new( - store_ptr: Option>, + store: &wasm_store_t, gt: &wasm_globaltype_t, val: &wasm_val_t, ) -> Option> { let gt = gt.as_globaltype(); let wasm_val = val.try_into().ok()?; - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); + let store = &store.inner; let global = if gt.mutability.is_mutable() { Global::new_mut(store, wasm_val) } else { diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index e44a636b057..2976f2e521b 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,8 +1,7 @@ use super::super::store::wasm_store_t; use super::super::types::wasm_memorytype_t; use std::mem; -use std::ptr::NonNull; -use wasmer::{Memory, Pages, Store}; +use wasmer::{Memory, Pages}; #[allow(non_camel_case_types)] pub struct wasm_memory_t { @@ -12,14 +11,12 @@ pub struct wasm_memory_t { #[no_mangle] pub unsafe extern "C" fn wasm_memory_new( - store_ptr: Option>, + store: &wasm_store_t, mt: &wasm_memorytype_t, ) -> Option> { let md = mt.as_memorytype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); + let memory = c_try!(Memory::new(&store.inner, md)); - let memory = c_try!(Memory::new(store, md)); Some(Box::new(wasm_memory_t { inner: memory })) } diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index f6ade8a5a76..526c36b2c7a 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,7 +1,6 @@ use super::super::store::wasm_store_t; use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; -use std::ptr::NonNull; -use wasmer::{Store, Table}; +use wasmer::Table; #[allow(non_camel_case_types)] pub struct wasm_table_t { @@ -11,17 +10,14 @@ pub struct wasm_table_t { #[no_mangle] pub unsafe extern "C" fn wasm_table_new( - store_ptr: Option>, + store: &wasm_store_t, tt: &wasm_tabletype_t, init: *const wasm_ref_t, ) -> Option> { let tt = tt.as_tabletype().clone(); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let init_val = todo!("get val from init somehow"); + let table = c_try!(Table::new(&store.inner, tt, init_val)); - let table = c_try!(Table::new(store, tt, init_val)); Some(Box::new(wasm_table_t { inner: table })) } diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 39a82fd284b..a79044a4ebf 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -4,7 +4,6 @@ use super::store::wasm_store_t; use super::trap::wasm_trap_t; use crate::ordered_resolver::OrderedResolver; use std::mem; -use std::ptr::NonNull; use std::sync::Arc; use wasmer::{Extern, Instance}; @@ -52,7 +51,7 @@ unsafe fn argument_import_iter( #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( - store: Option>, + _store: &wasm_store_t, module: &wasm_module_t, imports: *const *const wasm_extern_t, // own diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index a1e49ebc682..6e334097b04 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -7,7 +7,7 @@ use crate::error::update_last_error; use std::ptr::NonNull; use std::slice; use std::sync::Arc; -use wasmer::{Module, Store}; +use wasmer::Module; #[allow(non_camel_case_types)] pub struct wasm_module_t { @@ -16,14 +16,12 @@ pub struct wasm_module_t { #[no_mangle] pub unsafe extern "C" fn wasm_module_new( - store_ptr: Option>, + store: &wasm_store_t, bytes: &wasm_byte_vec_t, ) -> Option> { // TODO: review lifetime of byte slice let wasm_byte_slice: &[u8] = slice::from_raw_parts_mut(bytes.data, bytes.size); - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::from_binary(store, wasm_byte_slice)); + let module = c_try!(Module::from_binary(&store.inner, wasm_byte_slice)); Some(Box::new(wasm_module_t { inner: Arc::new(module), @@ -35,20 +33,13 @@ pub unsafe extern "C" fn wasm_module_delete(_module: Option>) #[no_mangle] pub unsafe extern "C" fn wasm_module_validate( - store_ptr: Option>, + store: &wasm_store_t, bytes: &wasm_byte_vec_t, ) -> bool { // TODO: review lifetime of byte slice. let wasm_byte_slice: &[u8] = slice::from_raw_parts(bytes.data, bytes.size); - if store_ptr.is_none() { - return false; - } - - let store_ptr = store_ptr.unwrap().cast::(); - let store = store_ptr.as_ref(); - - if let Err(error) = Module::validate(store, wasm_byte_slice) { + if let Err(error) = Module::validate(&store.inner, wasm_byte_slice) { update_last_error(error); false @@ -89,7 +80,7 @@ pub unsafe extern "C" fn wasm_module_imports( #[no_mangle] pub unsafe extern "C" fn wasm_module_deserialize( - store_ptr: Option>, + store: &wasm_store_t, bytes: *const wasm_byte_vec_t, ) -> Option> { // TODO: read config from store and use that to decide which compiler to use @@ -101,9 +92,7 @@ pub unsafe extern "C" fn wasm_module_deserialize( (&*bytes).into_slice().unwrap() }; - let store_ptr: NonNull = store_ptr?.cast::(); - let store = store_ptr.as_ref(); - let module = c_try!(Module::deserialize(store, byte_slice)); + let module = c_try!(Module::deserialize(&store.inner, byte_slice)); Some(NonNull::new_unchecked(Box::into_raw(Box::new( wasm_module_t { @@ -117,7 +106,7 @@ pub unsafe extern "C" fn wasm_module_serialize( module: &wasm_module_t, out_ptr: &mut wasm_byte_vec_t, ) { - let mut byte_vec = match module.inner.serialize() { + let byte_vec = match module.inner.serialize() { Ok(byte_vec) => byte_vec, Err(_) => return, }; diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index 6336f00334d..3a379ce9a0e 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -4,25 +4,20 @@ use wasmer::Store; /// Opaque wrapper around `Store` #[allow(non_camel_case_types)] -pub struct wasm_store_t {} +pub struct wasm_store_t { + pub(crate) inner: Store, +} #[no_mangle] pub unsafe extern "C" fn wasm_store_new( wasm_engine_ptr: Option>, -) -> Option> { +) -> Option> { let wasm_engine_ptr = wasm_engine_ptr?; let wasm_engine = wasm_engine_ptr.as_ref(); let store = Store::new(&*wasm_engine.inner); - Some(NonNull::new_unchecked( - Box::into_raw(Box::new(store)) as *mut wasm_store_t - )) + + Some(Box::new(wasm_store_t { inner: store })) } #[no_mangle] -pub unsafe extern "C" fn wasm_store_delete(wasm_store: Option>) { - if let Some(s_inner) = wasm_store { - // this should not leak memory: - // we should double check it to make sure though - let _: Box = Box::from_raw(s_inner.cast::().as_ptr()); - } -} +pub unsafe extern "C" fn wasm_store_delete(_store: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 86f8717d91f..cf0a08b73d4 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -16,9 +16,8 @@ use crate::error::{update_last_error, CApiError}; use std::convert::TryFrom; use std::ffi::CStr; use std::os::raw::c_char; -use std::ptr::NonNull; use std::slice; -use wasmer::{Extern, NamedResolver, Store}; +use wasmer::{Extern, NamedResolver}; use wasmer_wasi::{ generate_import_object_from_env, get_wasi_version, WasiEnv, WasiFile, WasiState, WasiStateBuilder, WasiVersion, @@ -241,7 +240,7 @@ pub unsafe extern "C" fn wasi_get_wasi_version(module: &wasm_module_t) -> wasi_v /// Takes ownership of `wasi_env_t`. #[no_mangle] pub unsafe extern "C" fn wasi_get_imports( - store: Option>, + store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, imports: *mut *mut wasm_extern_t, @@ -251,13 +250,12 @@ pub unsafe extern "C" fn wasi_get_imports( /// Takes ownership of `wasi_env_t`. unsafe fn wasi_get_imports_inner( - store: Option>, + store: &wasm_store_t, module: &wasm_module_t, wasi_env: &wasi_env_t, imports: *mut *mut wasm_extern_t, ) -> Option<()> { - let store_ptr = store?.cast::(); - let store = store_ptr.as_ref(); + let store = &store.inner; let version = c_try!( get_wasi_version(&module.inner, false).ok_or_else(|| CApiError {