diff --git a/CHANGELOG.md b/CHANGELOG.md index 5717edba5aa..1babe0f2c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ ### Fixed +- [#1855](https://github.com/wasmerio/wasmer/pull/1855) Fix memory leak when using `wat2wasm` in the C API, the function now takes its output parameter by pointer rather than returning an allocated `wasm_byte_vec_t`. - [#1841](https://github.com/wasmerio/wasmer/pull/1841) We will now panic when attempting to use a native function with a captured env as a host function. Previously this would silently do the wrong thing. See [#1840](https://github.com/wasmerio/wasmer/pull/1840) for info about Wasmer's support of closures as host functions. - [#1764](https://github.com/wasmerio/wasmer/pull/1764) Fix bug in WASI `path_rename` allowing renamed files to be 1 directory below a preopened directory. diff --git a/lib/c-api/src/deprecated/import/wasi.rs b/lib/c-api/src/deprecated/import/wasi.rs index aa94f523dab..6549053d5c8 100644 --- a/lib/c-api/src/deprecated/import/wasi.rs +++ b/lib/c-api/src/deprecated/import/wasi.rs @@ -212,7 +212,7 @@ pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object() -> *mut wa let store = get_global_store(); let mut wasi_state_builder = wasi::WasiState::new("wasmer-wasi-default-program-name"); let wasi_state = wasi_state_builder.build().unwrap(); - let mut wasi_env = wasi::WasiEnv::new(wasi_state); + let wasi_env = wasi::WasiEnv::new(wasi_state); let import_object_inner: Box = Box::new( wasi::generate_import_object_from_env(store, wasi_env, wasi::WasiVersion::Latest), ); diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index ffd95b701e9..c425d985da7 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -102,12 +102,13 @@ macro_rules! wasm_declare_vec { #[no_mangle] - pub unsafe extern "C" fn [](ptr: *mut []) { - let vec = &mut *ptr; - if !vec.data.is_null() { - Vec::from_raw_parts(vec.data, vec.size, vec.size); - vec.data = ::std::ptr::null_mut(); - vec.size = 0; + pub unsafe extern "C" fn [](ptr: Option<&mut []>) { + if let Some(vec) = ptr { + if !vec.data.is_null() { + Vec::from_raw_parts(vec.data, vec.size, vec.size); + vec.data = ::std::ptr::null_mut(); + vec.size = 0; + } } } } diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index e5f811dd855..92a71d17e59 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -38,12 +38,13 @@ pub struct wasm_module_t { /// /// wasm_byte_vec_t wat; /// wasmer_byte_vec_new_from_string(&wat, "(module)"); -/// wasm_byte_vec_t* wasm = wat2wasm(&wat); +/// wasm_byte_vec_t wasm; +/// wat2wasm(&wat, &wasm); /// -/// wasm_module_t* module = wasm_module_new(store, wasm); +/// wasm_module_t* module = wasm_module_new(store, &wasm); /// assert(module); /// -/// wasm_byte_vec_delete(wasm); +/// wasm_byte_vec_delete(&wasm); /// wasm_byte_vec_delete(&wat); /// wasm_module_delete(module); /// wasm_store_delete(store); @@ -190,11 +191,12 @@ mod tests { wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module)"); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - assert(wasm_module_validate(store, wasm)); + assert(wasm_module_validate(store, &wasm)); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); @@ -216,12 +218,13 @@ mod tests { wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module)"); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_module_delete(module); wasm_store_delete(store); @@ -251,9 +254,10 @@ mod tests { " (table (export \"table\") 0 funcref)\n" " (memory (export \"memory\") 1))" ); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); wasm_exporttype_vec_t export_types; @@ -328,7 +332,7 @@ mod tests { } wasm_exporttype_vec_delete(&export_types); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_module_delete(module); wasm_store_delete(store); @@ -356,9 +360,10 @@ mod tests { " (import \"ns\" \"table\" (table 1 2 anyfunc))\n" " (import \"ns\" \"memory\" (memory 3 4)))" ); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); wasm_importtype_vec_t import_types; @@ -444,7 +449,7 @@ mod tests { wasm_importtype_vec_delete(&import_types); wasm_module_delete(module); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); @@ -464,9 +469,10 @@ mod tests { wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module)"); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); wasm_byte_vec_t serialized_module; @@ -475,7 +481,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&serialized_module); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); @@ -502,9 +508,10 @@ mod tests { " (table (export \"table\") 0 funcref)\n" " (memory (export \"memory\") 1))" ); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - wasm_module_t* module = wasm_module_new(store, wasm); + wasm_module_t* module = wasm_module_new(store, &wasm); assert(module); wasm_byte_vec_t serialized_module; @@ -526,7 +533,7 @@ mod tests { wasm_exporttype_vec_delete(&export_types); wasm_module_delete(deserialized_module); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); 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 1a109bd8eeb..1ef66b35645 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -208,7 +208,7 @@ pub unsafe extern "C" fn wasi_env_read_stdout( buffer_len: usize, ) -> isize { let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize); - let mut state = env.inner.state_mut(); + let mut state = env.inner.state(); let stdout = if let Ok(stdout) = state.fs.stdout_mut() { if let Some(stdout) = stdout.as_mut() { @@ -232,7 +232,7 @@ pub unsafe extern "C" fn wasi_env_read_stderr( buffer_len: usize, ) -> isize { let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize); - let mut state = env.inner.state_mut(); + let mut state = env.inner.state(); let stderr = if let Ok(stderr) = state.fs.stderr_mut() { if let Some(stderr) = stderr.as_mut() { stderr diff --git a/lib/c-api/src/wasm_c_api/wat.rs b/lib/c-api/src/wasm_c_api/wat.rs index 185b61e91c0..c37010a8a78 100644 --- a/lib/c-api/src/wasm_c_api/wat.rs +++ b/lib/c-api/src/wasm_c_api/wat.rs @@ -3,14 +3,29 @@ use super::types::wasm_byte_vec_t; /// Parses in-memory bytes as either the WAT format, or a binary Wasm /// module. This is wasmer-specific. /// -/// In case of failure, `wat2wasm` returns `NULL`. +/// In case of failure, `wat2wasm` sets the `out->data = NULL` and `out->size = 0`. #[cfg(feature = "wat")] #[no_mangle] -pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t) -> Option> { - let wat: &[u8] = wat.into_slice()?; - let result: wasm_byte_vec_t = c_try!(wasmer::wat2wasm(wat)).into_owned().into(); +pub unsafe extern "C" fn wat2wasm(wat: &wasm_byte_vec_t, out: &mut wasm_byte_vec_t) { + let wat: &[u8] = match wat.into_slice() { + Some(v) => v, + _ => { + out.data = std::ptr::null_mut(); + out.size = 0; + return; + } + }; + let result: wasm_byte_vec_t = match wasmer::wat2wasm(wat) { + Ok(val) => val.into_owned().into(), + Err(err) => { + crate::error::update_last_error(err); + out.data = std::ptr::null_mut(); + out.size = 0; + return; + } + }; - Some(Box::new(result)) + *out = result; } #[cfg(test)] @@ -28,22 +43,23 @@ mod tests { wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module)"); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - assert(wasm); - assert(wasm->size == 8); + assert(wasm.data); + assert(wasm.size == 8); assert( - wasm->data[0] == 0 && - wasm->data[1] == 'a' && - wasm->data[2] == 's' && - wasm->data[3] == 'm' && - wasm->data[4] == 1 && - wasm->data[5] == 0 && - wasm->data[6] == 0 && - wasm->data[7] == 0 + wasm.data[0] == 0 && + wasm.data[1] == 'a' && + wasm.data[2] == 's' && + wasm.data[3] == 'm' && + wasm.data[4] == 1 && + wasm.data[5] == 0 && + wasm.data[6] == 0 && + wasm.data[7] == 0 ); - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); wasm_store_delete(store); wasm_engine_delete(engine); @@ -65,9 +81,10 @@ mod tests { wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module"); - wasm_byte_vec_t* wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - assert(!wasm); + assert(!wasm.data); assert(wasmer_last_error_length() > 0); wasm_byte_vec_delete(&wat); diff --git a/lib/c-api/tests/wasm_c_api/test-wat2wasm.c b/lib/c-api/tests/wasm_c_api/test-wat2wasm.c index 5897cadadbe..51b785ca50e 100644 --- a/lib/c-api/tests/wasm_c_api/test-wat2wasm.c +++ b/lib/c-api/tests/wasm_c_api/test-wat2wasm.c @@ -20,31 +20,32 @@ int main(int argc, const char* argv[]) { .data = "(module)", .size = 8, }; - wasm_byte_vec_t *wasm = wat2wasm(&wat); + wasm_byte_vec_t wasm; + wat2wasm(&wat, &wasm); - if (!wasm) { - printf("> Error compiler WAT to Wasm!\n"); + if (!wasm.data) { + printf("> Error compiling WAT to Wasm!\n"); return 1; } - if (wasm->size != 8) { + if (wasm.size != 8) { printf("The Wasm size is incorrect!\n"); return 1; } - if (!(wasm->data[0] == 0 && - wasm->data[1] == 'a' && - wasm->data[2] == 's' && - wasm->data[3] == 'm' && - wasm->data[4] == 1 && - wasm->data[5] == 0 && - wasm->data[6] == 0 && - wasm->data[7] == 0)) { + if (!(wasm.data[0] == 0 && + wasm.data[1] == 'a' && + wasm.data[2] == 's' && + wasm.data[3] == 'm' && + wasm.data[4] == 1 && + wasm.data[5] == 0 && + wasm.data[6] == 0 && + wasm.data[7] == 0)) { printf("The Wasm data is incorrect!\n"); return 1; } - wasm_byte_vec_delete(wasm); + wasm_byte_vec_delete(&wasm); // All done. printf("Done.\n"); diff --git a/lib/c-api/wasmer_wasm.h b/lib/c-api/wasmer_wasm.h index 3e2916c21bb..9f1a47e8a1e 100644 --- a/lib/c-api/wasmer_wasm.h +++ b/lib/c-api/wasmer_wasm.h @@ -237,8 +237,8 @@ int wasmer_last_error_message(char *buffer, int length); * Parses in-memory bytes as either the WAT format, or a binary Wasm * module. This is wasmer-specific. * - * In case of failure, `wat2wasm` returns `NULL`. + * In case of failure, `wat2wasm` sets the `out->data = NULL` and `out->size = 0`. */ -wasm_byte_vec_t *wat2wasm(const wasm_byte_vec_t *wat); +void wat2wasm(const wasm_byte_vec_t *wat, wasm_byte_vec_t *out); #endif /* WASMER_WASM_H */