diff --git a/CHANGELOG.md b/CHANGELOG.md index 90d14ded237..62805ceb3ff 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 - [#1099](https://github.com/wasmerio/wasmer/pull/1099) Remove `backend::Backend` from `wasmer_runtime_core` - [#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. diff --git a/Cargo.lock b/Cargo.lock index 27ee3e30d5c..f088c25da23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83b7baab1e671718d78204225800d6b170e648188ac7dc992e9d6bddf87d0c0" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" dependencies = [ "arrayref", "arrayvec", @@ -452,9 +452,9 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" [[package]] name = "generational-arena" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675c9623fbcdb4b402176db720bf5d95883a36303703ed1bd3a03482382f735a" +checksum = "0e40d0cee2e2fb4fba18b55a27bf96faf49fa86d49f178695bd3bf4500b156b4" dependencies = [ "cfg-if", "serde", @@ -901,13 +901,28 @@ checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "proc-macro-error" -version = "0.2.6" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c98547ceaea14eeb26fcadf51dc70d01a2479a7839170eae133721105e4428" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.6", + "quote 1.0.2", + "rustversion", + "syn 1.0.11", +] + +[[package]] +name = "proc-macro-error-attr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +checksum = "c2bf5d493cf5d3e296beccfd61794e445e830dfc8070a9c248ad3ee071392c6c" dependencies = [ "proc-macro2 1.0.6", "quote 1.0.2", + "rustversion", "syn 1.0.11", + "syn-mid", ] [[package]] @@ -1116,9 +1131,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" dependencies = [ "crossbeam-deque", "either", @@ -1127,9 +1142,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" dependencies = [ "crossbeam-deque", "crossbeam-queue", @@ -1204,6 +1219,17 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0538bd897e17257b0128d2fd95c2ed6df939374073a36166051a79e2eb7986" +dependencies = [ + "proc-macro2 1.0.6", + "quote 1.0.2", + "syn 1.0.11", +] + [[package]] name = "ryu" version = "1.0.2" @@ -1364,9 +1390,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" +checksum = "884ae79d6aad1e738f4a70dff314203fd498490a63ebc4d03ea83323c40b7b72" dependencies = [ "clap", "structopt-derive", @@ -1374,9 +1400,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" +checksum = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93" dependencies = [ "heck", "proc-macro-error", @@ -1407,6 +1433,17 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "syn-mid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0" +dependencies = [ + "proc-macro2 1.0.6", + "quote 1.0.2", + "syn 1.0.11", +] + [[package]] name = "target-lexicon" version = "0.9.0" @@ -1708,7 +1745,7 @@ dependencies = [ "regex", "rustc_version", "semver", - "smallvec 0.6.13", + "smallvec 1.1.0", "wabt", "wasmer-runtime-core", "wasmparser", @@ -1795,7 +1832,7 @@ dependencies = [ "serde-bench", "serde_bytes", "serde_derive", - "smallvec 0.6.13", + "smallvec 1.1.0", "wasmparser", "winapi", ] @@ -1824,7 +1861,7 @@ dependencies = [ "nix", "serde", "serde_derive", - "smallvec 0.6.13", + "smallvec 1.1.0", "wasmer-runtime-core", ] diff --git a/lib/runtime-c-api/build.rs b/lib/runtime-c-api/build.rs index 3b54a6c4214..370d434a7cf 100644 --- a/lib/runtime-c-api/build.rs +++ b/lib/runtime-c-api/build.rs @@ -14,18 +14,31 @@ fn main() { let mut pre_header = r#" #if !defined(WASMER_H_MACROS) + #define WASMER_H_MACROS -#if defined(MSVC) -#if defined(_M_AMD64) -#define ARCH_X86_64 +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 #endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 #endif -#if defined(GCC) || defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) -#define ARCH_X86_64 +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 #endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) #endif "# @@ -41,7 +54,7 @@ fn main() { pre_header += "#define WASMER_EMSCRIPTEN_ENABLED\n"; } - // close pre header + // Close pre header. pre_header += "#endif // WASMER_H_MACROS\n"; // Generate the C bindings in the `OUT_DIR`. diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 5bb86b42212..1c3bf4c7ea4 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -1,17 +1,30 @@ #if !defined(WASMER_H_MACROS) + #define WASMER_H_MACROS -#if defined(MSVC) -#if defined(_M_AMD64) -#define ARCH_X86_64 +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 #endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 #endif -#if defined(GCC) || defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) -#define ARCH_X86_64 +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 #endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) #endif #define WASMER_WASI_ENABLED diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index fe0fcd7f546..0f4f44441a0 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -1,17 +1,30 @@ #if !defined(WASMER_H_MACROS) + #define WASMER_H_MACROS -#if defined(MSVC) -#if defined(_M_AMD64) -#define ARCH_X86_64 +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 #endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 #endif -#if defined(GCC) || defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) -#define ARCH_X86_64 +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 #endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) #endif #define WASMER_WASI_ENABLED diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 1b50abaf6ab..cf787675228 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; @@ -563,7 +560,11 @@ 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()) }; + 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) }; + } } } } @@ -650,9 +651,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 a653725abf5..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 { @@ -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::*; diff --git a/lib/runtime/tests/allow_missing_functions.rs b/lib/runtime/tests/allow_missing_functions.rs new file mode 100644 index 00000000000..152634cf484 --- /dev/null +++ b/lib/runtime/tests/allow_missing_functions.rs @@ -0,0 +1,24 @@ +#[test] +fn allow_missing() { + use wabt::wat2wasm; + use wasmer_runtime::{imports, instantiate}; + + static WAT: &'static str = r#" + (module + (type (;0;) (func)) + (type (;1;) (func (result i32))) + (import "env" "ret_err" (func $ret_err (type 0))) + (func $get_num (type 1) + i32.const 42 + ) + (export "get_num" (func $get_num)) + ) + "#; + + let wasm = wat2wasm(WAT).unwrap(); + + let mut import_object = imports! {}; + import_object.allow_missing_functions = true; + + assert!(instantiate(&wasm, &import_object).is_ok()); +} 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(); diff --git a/lib/wasi-experimental-io-devices/src/lib.rs b/lib/wasi-experimental-io-devices/src/lib.rs index d713a18af8c..e5acd15c841 100644 --- a/lib/wasi-experimental-io-devices/src/lib.rs +++ b/lib/wasi-experimental-io-devices/src/lib.rs @@ -81,7 +81,7 @@ impl FrameBufferState { y, WindowOptions { resize: true, - scale: Scale::X4, + scale: Scale::FitScreen, ..WindowOptions::default() }, ) @@ -114,6 +114,9 @@ impl FrameBufferState { pub fn fill_input_buffer(&mut self) -> Option<()> { let keys_pressed = self.keys_pressed.iter().cloned().collect::>(); + if !self.window.is_open() { + self.push_input_event(InputEvent::WindowClosed)?; + } for key in keys_pressed { if self.window.is_key_released(key) { self.keys_pressed.remove(&key); diff --git a/lib/wasi-experimental-io-devices/src/util.rs b/lib/wasi-experimental-io-devices/src/util.rs index a3e4daf087a..1b6107505e3 100644 --- a/lib/wasi-experimental-io-devices/src/util.rs +++ b/lib/wasi-experimental-io-devices/src/util.rs @@ -6,6 +6,7 @@ pub const KEY_RELEASE: u8 = 3; pub const MOUSE_PRESS_LEFT: u8 = 4; pub const MOUSE_PRESS_RIGHT: u8 = 5; pub const MOUSE_PRESS_MIDDLE: u8 = 7; +pub const WINDOW_CLOSED: u8 = 8; use minifb::{Key, MouseButton}; @@ -15,6 +16,7 @@ pub enum InputEvent { KeyRelease(Key), MouseEvent(u32, u32, MouseButton), MouseMoved(u32, u32), + WindowClosed, } /// Returns the tag as the first return value @@ -58,6 +60,7 @@ pub fn bytes_for_input_event(input_event: InputEvent) -> (u8, [u8; 8], usize) { } (MOUSE_MOVE, data, 8) } + InputEvent::WindowClosed => (WINDOW_CLOSED, data, 0), } } diff --git a/wapm-cli b/wapm-cli index 3562d6dda52..e2d3eb18f30 160000 --- a/wapm-cli +++ b/wapm-cli @@ -1 +1 @@ -Subproject commit 3562d6dda52df526e6e1917dd33bb2454917ab9c +Subproject commit e2d3eb18f304e165b5840aebba1917f9d14c77b4