diff --git a/lib/middleware-common/src/metering.rs b/lib/middleware-common/src/metering.rs index 7e2fd44d6..436a0d50a 100644 --- a/lib/middleware-common/src/metering.rs +++ b/lib/middleware-common/src/metering.rs @@ -34,6 +34,9 @@ impl Metering { } } +#[derive(Copy, Clone, Debug)] +pub struct ExecutionLimitExceededError; + impl FunctionMiddleware for Metering { type Error = String; fn feed_event<'a, 'b: 'a>( @@ -93,9 +96,8 @@ impl FunctionMiddleware for Metering { })); sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new( move |ctx| { - eprintln!("execution limit reached"); unsafe { - (ctx.throw)(); + (ctx.throw)(Box::new(ExecutionLimitExceededError)); } }, )))); @@ -251,6 +253,7 @@ mod tests { #[test] fn test_traps_after_costly_call() { + use wasmer_runtime_core::error::RuntimeError; let wasm_binary = wat2wasm(WAT).unwrap(); let limit = 100u64; @@ -265,8 +268,13 @@ mod tests { let add_to: Func<(i32, i32), i32> = instance.func("add_to").unwrap(); let result = add_to.call(10_000_000, 4); - // verify it errors - assert_eq!(result.is_err(), true); // TODO assert that the trap is caused by PointsExausted + let err = result.unwrap_err(); + match err { + RuntimeError::Error { data } => { + assert!(data.downcast_ref::().is_some()); + }, + _ => unreachable!(), + } // verify is uses the correct number of points assert_eq!(get_points_used(&instance), 109); // Used points will be slightly more than `limit` because of the way we do gas checking. diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 71a38dc88..4ff0c25cb 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -8,6 +8,7 @@ use crate::{ types::{FuncIndex, FuncSig, SigIndex}, }; use smallvec::SmallVec; +use std::any::Any; use std::fmt; use std::fmt::Debug; use std::marker::PhantomData; @@ -43,7 +44,7 @@ impl fmt::Debug for InternalEvent { } pub struct BkptInfo { - pub throw: unsafe extern "C" fn() -> !, + pub throw: unsafe fn(Box) -> !, } pub trait ModuleCodeGenerator, RM: RunnableModule, E: Debug> { diff --git a/lib/singlepass-backend/src/protect_unix.rs b/lib/singlepass-backend/src/protect_unix.rs index 56ac61519..f777c2482 100644 --- a/lib/singlepass-backend/src/protect_unix.rs +++ b/lib/singlepass-backend/src/protect_unix.rs @@ -128,11 +128,12 @@ pub fn call_protected(f: impl FnOnce() -> T) -> Result { } } -pub unsafe extern "C" fn throw() -> ! { +pub unsafe fn throw(payload: Box) -> ! { let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get()); if *jmp_buf == [0; SETJMP_BUFFER_LEN] { ::std::process::abort(); } + TRAP_EARLY_DATA.with(|cell| cell.replace(Some(payload))); longjmp(jmp_buf as *mut ::nix::libc::c_void, 0xffff); } diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 848b1044e..7a2506ac8 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -33,6 +33,7 @@ use wasmer_runtime_core::{ use wasmer_singlepass_backend::ModuleCodeGenerator as SinglePassMCG; #[cfg(feature = "wasi")] use wasmer_wasi; +use wasmer_middleware_common::metering::Metering; // stub module to make conditional compilation happy #[cfg(not(feature = "wasi"))]