From d91cf82ab56fbf7873eb10b6a17508f4b1f0b613 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 1 Feb 2020 10:30:51 -0800 Subject: [PATCH] Verify correct number and types of arguments enter wasm Whenever we enter wasm code we need to verify that the correct number and the correct types of arguments were passed in, lest we misinterpret bits! Closes #52 --- crates/api/src/callable.rs | 23 ++++++++++++++++++++--- crates/api/tests/traps.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/crates/api/src/callable.rs b/crates/api/src/callable.rs index edeee6f23c8c..2e59b39e12db 100644 --- a/crates/api/src/callable.rs +++ b/crates/api/src/callable.rs @@ -127,15 +127,32 @@ impl WrappedCallable for WasmtimeFn { } => (*vmctx, *address, signature.clone()), _ => panic!("unexpected export type in Callable"), }; + if signature.params.len() - 2 != params.len() { + return Err(Trap::new(format!( + "expected {} arguments, got {}", + signature.params.len() - 2, + params.len() + ))); + } + if signature.returns.len() != results.len() { + return Err(Trap::new(format!( + "expected {} results, got {}", + signature.returns.len(), + results.len() + ))); + } let value_size = mem::size_of::(); let mut values_vec = vec![0; max(params.len(), results.len())]; // Store the argument values into `values_vec`. - for (index, arg) in params.iter().enumerate() { + let param_tys = signature.params.iter().skip(2); + for ((arg, slot), ty) in params.iter().zip(&mut values_vec).zip(param_tys) { + if arg.ty().get_wasmtime_type() != Some(ty.value_type) { + return Err(Trap::new("argument type mismatch")); + } unsafe { - let ptr = values_vec.as_mut_ptr().add(index); - arg.write_value_to(ptr); + arg.write_value_to(slot); } } diff --git a/crates/api/tests/traps.rs b/crates/api/tests/traps.rs index c5b221ff28e0..a5dbbadf48c0 100644 --- a/crates/api/tests/traps.rs +++ b/crates/api/tests/traps.rs @@ -308,3 +308,34 @@ fn rust_panic_start_function() -> Result<()> { assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); Ok(()) } + +#[test] +fn mismatched_arguments() -> Result<()> { + let store = Store::default(); + let binary = wat::parse_str( + r#" + (module $a + (func (export "foo") (param i32)) + ) + "#, + )?; + + let module = Module::new(&store, &binary)?; + let instance = Instance::new(&module, &[])?; + let func = instance.exports()[0].func().unwrap().clone(); + assert_eq!( + func.call(&[]).unwrap_err().message(), + "expected 1 arguments, got 0" + ); + assert_eq!( + func.call(&[Val::F32(0)]).unwrap_err().message(), + "argument type mismatch", + ); + assert_eq!( + func.call(&[Val::I32(0), Val::I32(1)]) + .unwrap_err() + .message(), + "expected 1 arguments, got 2" + ); + Ok(()) +}