mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-18 17:10:52 +00:00
feat(interface-types) Check signature of the exported function to call.
This commit is contained in:
parent
b7b37d2e99
commit
56afb4da63
@ -1,6 +1,6 @@
|
||||
use crate::instructions::{
|
||||
stack::{Stack, Stackable},
|
||||
wasm::{self, Value},
|
||||
wasm::{self, Type, Value},
|
||||
Instruction,
|
||||
};
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
@ -105,6 +105,20 @@ where
|
||||
|
||||
match runtime.stack.pop(inputs_cardinality) {
|
||||
Some(inputs) => {
|
||||
let input_types = inputs
|
||||
.iter()
|
||||
.map(|input| input.into())
|
||||
.collect::<Vec<Type>>();
|
||||
|
||||
if input_types != export.inputs() {
|
||||
return Err(format!(
|
||||
"`{}` cannot call the exported function `{}` because the value types in the stack mismatch the function signature (expects {:?}).",
|
||||
instruction_name,
|
||||
export_name,
|
||||
export.inputs(),
|
||||
))
|
||||
}
|
||||
|
||||
match export.call(&inputs) {
|
||||
Ok(outputs) => {
|
||||
for output in outputs.iter() {
|
||||
@ -117,7 +131,7 @@ where
|
||||
}
|
||||
}
|
||||
None => Err(format!(
|
||||
"`{}` cannot call the exported function `{}` because there is no enought data in the stack for the arguments (need {}).",
|
||||
"`{}` cannot call the exported function `{}` because there is no enought data in the stack for the arguments (needs {}).",
|
||||
instruction_name,
|
||||
export_name,
|
||||
inputs_cardinality,
|
||||
@ -339,4 +353,53 @@ mod tests {
|
||||
String::from(r#"`call-export "bar"` cannot call the exported function `bar` because it doesn't exist."#)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interpreter_call_export_too_small_stack() {
|
||||
let interpreter: Interpreter<Instance, Export> = (&vec![
|
||||
Instruction::ArgumentGet(0),
|
||||
Instruction::CallExport("sum"),
|
||||
// ^^^ `sum` expects 2 values in the stack, only one is present
|
||||
])
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
let invocation_inputs = vec![Value::I32(3), Value::I32(4)];
|
||||
let instance = Instance::new();
|
||||
let run = interpreter.run(&invocation_inputs, &instance);
|
||||
|
||||
assert!(run.is_err());
|
||||
|
||||
let error = run.unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
error,
|
||||
String::from(r#"`call-export "sum"` cannot call the exported function `sum` because there is no enought data in the stack for the arguments (needs 2)."#)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interpreter_call_export_invalid_types_in_the_stack() {
|
||||
let interpreter: Interpreter<Instance, Export> = (&vec![
|
||||
Instruction::ArgumentGet(1),
|
||||
Instruction::ArgumentGet(0),
|
||||
Instruction::CallExport("sum"),
|
||||
])
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
let invocation_inputs = vec![Value::I32(3), Value::I64(4)];
|
||||
// ^^^ mismatch with `sum` signature
|
||||
let instance = Instance::new();
|
||||
let run = interpreter.run(&invocation_inputs, &instance);
|
||||
|
||||
assert!(run.is_err());
|
||||
|
||||
let error = run.unwrap_err();
|
||||
|
||||
assert_eq!(
|
||||
error,
|
||||
String::from(r#"`call-export "sum"` cannot call the exported function `sum` because the value types in the stack mismatch the function signature (expects [I32, I32])."#)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Type {
|
||||
I32,
|
||||
I64,
|
||||
@ -17,6 +18,18 @@ pub enum Value {
|
||||
V128(u128),
|
||||
}
|
||||
|
||||
impl From<&Value> for Type {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
Value::I32(_) => Type::I32,
|
||||
Value::I64(_) => Type::I64,
|
||||
Value::F32(_) => Type::F32,
|
||||
Value::F64(_) => Type::F64,
|
||||
Value::V128(_) => Type::V128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
fn default() -> Self {
|
||||
Self::I32(0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user