From cd6e4bdaeeb93de5e3ac43e3c46bffcb3747619b Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 9 Jan 2020 15:10:23 +0100 Subject: [PATCH 1/6] test(runtime) Fix CS. --- lib/runtime/tests/error_propagation.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/runtime/tests/error_propagation.rs b/lib/runtime/tests/error_propagation.rs index 1b9f9fccfbf..44cfa3fd943 100644 --- a/lib/runtime/tests/error_propagation.rs +++ b/lib/runtime/tests/error_propagation.rs @@ -30,9 +30,9 @@ fn error_propagation() { let instance = module .instantiate(&imports! { - "env" => { - "ret_err" => Func::new(ret_err), - }, + "env" => { + "ret_err" => Func::new(ret_err), + }, }) .unwrap(); From 19c38378818780bd066b575d957be431b23d009f Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 9 Jan 2020 15:10:53 +0100 Subject: [PATCH 2/6] feat(runtime-core) Create the `always_trap` host function. --- lib/runtime-core/src/typed_func.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index a653725abf5..24f35bd6944 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -733,6 +733,12 @@ where } } +/// Function that always fails. It can be used as a placeholder when a +/// host function is missing for instance. +pub(crate) fn always_trap() -> Result<(), &'static str> { + Err("not implemented") +} + #[cfg(test)] mod tests { use super::*; From 6018aa32e1c90152b59f9e442cfeebf288f58229 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 9 Jan 2020 15:11:25 +0100 Subject: [PATCH 3/6] fix(runtime-core) Drop `vm::FuncCtx` if not null. --- lib/runtime-core/src/backing.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 1b50abaf6ab..21fed0c42d9 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -563,7 +563,9 @@ impl Drop for ImportBacking { fn drop(&mut self) { // Properly drop the `vm::FuncCtx` in `vm::ImportedFunc`. for (_imported_func_index, imported_func) in (*self.vm_functions).iter_mut() { - let _: Box = unsafe { Box::from_raw(imported_func.func_ctx.as_ptr()) }; + if !imported_func.func_ctx.as_ptr().is_null() { + let _: Box = unsafe { Box::from_raw(imported_func.func_ctx.as_ptr()) }; + } } } } From c81e49a091847c7c5cfc37959f09b1ea4c361741 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 9 Jan 2020 15:12:09 +0100 Subject: [PATCH 4/6] feat(runtime-core) Replace missing host function by `always_trap`. --- lib/runtime-core/src/backing.rs | 20 +++++++++++++------- lib/runtime-core/src/typed_func.rs | 10 +++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 21fed0c42d9..437f5f724a9 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -8,6 +8,7 @@ use crate::{ sig_registry::SigRegistry, structures::{BoxedMap, Map, SliceMap, TypedIndex}, table::Table, + typed_func::{always_trap, Func}, types::{ ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalFuncIndex, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, @@ -15,11 +16,7 @@ use crate::{ }, vm, }; -use std::{ - fmt::Debug, - ptr::{self, NonNull}, - slice, -}; +use std::{fmt::Debug, ptr::NonNull, slice}; /// Size of the array for internal instance usage pub const INTERNALS_SIZE: usize = 256; @@ -652,9 +649,18 @@ fn import_functions( } None => { if imports.allow_missing_functions { + let always_trap = Func::new(always_trap); + functions.push(vm::ImportedFunc { - func: ptr::null(), - func_ctx: unsafe { NonNull::new_unchecked(ptr::null_mut()) }, // TODO: Non-sense… + func: always_trap.get_vm_func().as_ptr(), + func_ctx: NonNull::new(Box::into_raw(Box::new(vm::FuncCtx { + // ^^^^^^^^ `vm::FuncCtx` is purposely leaked. + // It is dropped by the specific `Drop` + // implementation of `ImportBacking`. + vmctx: NonNull::new(vmctx).expect("`vmctx` must not be null."), + func_env: None, + }))) + .unwrap(), }); } else { link_errors.push(LinkError::ImportNotFound { diff --git a/lib/runtime-core/src/typed_func.rs b/lib/runtime-core/src/typed_func.rs index 24f35bd6944..9de9d40e2e3 100644 --- a/lib/runtime-core/src/typed_func.rs +++ b/lib/runtime-core/src/typed_func.rs @@ -258,11 +258,6 @@ where _phantom: PhantomData, } } - - /// Get the underlying func pointer. - pub fn get_vm_func(&self) -> NonNull { - self.func - } } impl<'a, Args, Rets> Func<'a, Args, Rets, Host> @@ -303,6 +298,11 @@ where pub fn returns(&self) -> &'static [Type] { Rets::types() } + + /// Get the underlying func pointer. + pub fn get_vm_func(&self) -> NonNull { + self.func + } } impl WasmTypeList for Infallible { From 9b2f0fc635a5de2e5c07647a7dc7d508c965e5da Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 10:15:26 +0100 Subject: [PATCH 5/6] chore(runtime-core) Avoid code duplication. --- lib/runtime-core/src/backing.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 437f5f724a9..cf787675228 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -560,8 +560,10 @@ impl Drop for ImportBacking { fn drop(&mut self) { // Properly drop the `vm::FuncCtx` in `vm::ImportedFunc`. for (_imported_func_index, imported_func) in (*self.vm_functions).iter_mut() { - if !imported_func.func_ctx.as_ptr().is_null() { - let _: Box = unsafe { Box::from_raw(imported_func.func_ctx.as_ptr()) }; + let func_ctx_ptr = imported_func.func_ctx.as_ptr(); + + if !func_ctx_ptr.is_null() { + let _: Box = unsafe { Box::from_raw(func_ctx_ptr) }; } } } From 43742cf980ce000c044c231c40ec6515ef6834a8 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 10 Jan 2020 10:18:51 +0100 Subject: [PATCH 6/6] doc(changelog) Add #1128. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f9528b5f48..fe82692b441 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## **[Unreleased]** +- [#1128](https://github.com/wasmerio/wasmer/pull/1128) Fix a crash when a host function is missing and the `allow_missing_functions` flag is enabled - [#1097](https://github.com/wasmerio/wasmer/pull/1097) Move inline breakpoint outside of runtime backend - [#1095](https://github.com/wasmerio/wasmer/pull/1095) Update to cranelift 0.52. - [#1092](https://github.com/wasmerio/wasmer/pull/1092) Add `get_utf8_string_with_nul` to `WasmPtr` to read nul-terminated strings from memory.