Verify correct number and types of arguments enter wasm (#890)
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
This commit is contained in:
@@ -127,15 +127,32 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
} => (*vmctx, *address, signature.clone()),
|
} => (*vmctx, *address, signature.clone()),
|
||||||
_ => panic!("unexpected export type in Callable"),
|
_ => 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::<u128>();
|
let value_size = mem::size_of::<u128>();
|
||||||
let mut values_vec = vec![0; max(params.len(), results.len())];
|
let mut values_vec = vec![0; max(params.len(), results.len())];
|
||||||
|
|
||||||
// Store the argument values into `values_vec`.
|
// 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 {
|
unsafe {
|
||||||
let ptr = values_vec.as_mut_ptr().add(index);
|
arg.write_value_to(slot);
|
||||||
arg.write_value_to(ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -308,3 +308,34 @@ fn rust_panic_start_function() -> Result<()> {
|
|||||||
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user