diff --git a/src/interpreter/env_native.rs b/src/interpreter/env_native.rs index ecde8c3..bbf1a9e 100644 --- a/src/interpreter/env_native.rs +++ b/src/interpreter/env_native.rs @@ -125,21 +125,51 @@ impl<'a, E> ModuleInstanceInterface for NativeModuleInstance<'a, E> where E: let composite_index = NATIVE_INDEX_FUNC_MIN + *index; match required_type { &ExportEntryType::Any => return Ok(Internal::Function(composite_index)), - &ExportEntryType::Function(ref required_type) - if self.function_type(ItemIndex::Internal(composite_index)) - .expect("by_name contains index; function_type succeeds for all functions from by_name; qed") == *required_type - => return Ok(Internal::Function(composite_index)), + &ExportEntryType::Function(ref required_type) => { + let actual_type = self.function_type(ItemIndex::Internal(composite_index)) + .expect( + "by_name contains index; function_type succeeds for all functions from by_name; qed", + ); + return if actual_type == *required_type { + Ok(Internal::Function(composite_index)) + } else { + Err(Error::Validation(format!( + "Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}", + index, + required_type.params(), + required_type.return_type(), + actual_type.params(), + actual_type.return_type() + ))) + }; + } _ => (), } } if let Some(index) = self.globals_by_name.get(name) { + let composite_index = NATIVE_INDEX_GLOBAL_MIN + *index; match required_type { - &ExportEntryType::Any => return Ok(Internal::Global(NATIVE_INDEX_GLOBAL_MIN + *index)), - &ExportEntryType::Global(ref required_type) - if self.globals.get(*index as usize) - .expect("globals_by_name maps to indexes of globals; index read from globals_by_name; qed") - .variable_type() == *required_type - => return Ok(Internal::Global(NATIVE_INDEX_GLOBAL_MIN + *index)), + &ExportEntryType::Any => { + return Ok(Internal::Global(composite_index)) + } + &ExportEntryType::Global(ref required_type) => { + let actual_type = self.globals + .get(*index as usize) + .expect( + "globals_by_name maps to indexes of globals; index read from globals_by_name; qed", + ) + .variable_type(); + return if actual_type == *required_type { + Ok(Internal::Global(composite_index)) + } else { + Err(Error::Validation(format!( + "Export global type {} mismatch. Expected type {:?} when got {:?}", + index, + required_type, + actual_type + ))) + }; + } _ => (), } } @@ -227,4 +257,4 @@ impl<'a> PartialEq for UserFunctionDescriptor { self.params() == other.params() && self.return_type() == other.return_type() } -} \ No newline at end of file +} diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index 4169e35..69f641a 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -285,18 +285,18 @@ impl ModuleInstance where E: UserError { // export entry points to function in function index space // and Internal::Function points to type in type section - { - let export_function_type = match export_entry { - Internal::Function(function_index) => external_module.function_type(ItemIndex::IndexSpace(function_index))?, - _ => return Err(Error::Validation(format!("Export with name {} from module {} is not a function", import.field(), import.module()))), - }; - - if export_function_type != import_function_type { - return Err(Error::Validation(format!("Export function type {} mismatch. Expected function with signature ({:?}) -> {:?} when got with ({:?}) -> {:?}", - function_type_index, import_function_type.params(), import_function_type.return_type(), - export_function_type.params(), export_function_type.return_type()))); + match export_entry { + Internal::Function(function_index) => { + external_module.function_type(ItemIndex::IndexSpace(function_index))? } - } + _ => { + return Err(Error::Validation(format!( + "Export with name {} from module {} is not a function", + import.field(), + import.module() + ))) + } + }; }, &External::Global(ref global_type) => if global_type.is_mutable() { return Err(Error::Validation(format!("trying to import mutable global {}", import.field()))); diff --git a/src/interpreter/tests/basics.rs b/src/interpreter/tests/basics.rs index 4414ef0..bca315e 100644 --- a/src/interpreter/tests/basics.rs +++ b/src/interpreter/tests/basics.rs @@ -76,7 +76,7 @@ fn wrong_import() { let program = DefaultProgramInstance::new().unwrap(); let _side_module_instance = program.add_module("side_module", side_module, None).unwrap(); - assert!(program.add_module("main", module, None).is_err()); + assert!(program.add_module("main", module, None).is_err()); } #[test] @@ -314,7 +314,7 @@ fn native_env_function_own_memory() { let module_instance = program.add_module("main", module, Some(¶ms.externals)).unwrap(); // now get memory reference let module_memory = module_instance.memory(ItemIndex::Internal(0)).unwrap(); - // post-initialize our executor with memory reference + // post-initialize our executor with memory reference *memory_ref.memory.borrow_mut() = Some(module_memory); // now execute function => executor updates memory @@ -427,14 +427,29 @@ fn env_native_export_entry_type_check() { }; let native_env_instance = Arc::new(env_native_module(program.module("env").unwrap(), UserDefinedElements { executor: Some(&mut function_executor), - globals: HashMap::new(), + globals: vec![("ext_global".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(1312)).unwrap()))].into_iter().collect(), functions: ::std::borrow::Cow::from(SIGNATURES), }).unwrap()); assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I32))))).is_ok()); - assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))).is_err()); - assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))).is_err()); - assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))).is_err()); + match native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))) { + Err(Error::Validation(_)) => { }, + result => panic!("Unexpected result {:?}.", result), + } + match native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))) { + Err(Error::Validation(_)) => { }, + result => panic!("Unexpected result {:?}.", result), + } + match native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))) { + Err(Error::Validation(_)) => { }, + result => panic!("Unexpected result {:?}.", result), + } + + assert!(native_env_instance.export_entry("ext_global", &ExportEntryType::Global(VariableType::I32)).is_ok()); + match native_env_instance.export_entry("ext_global", &ExportEntryType::Global(VariableType::F32)) { + Err(Error::Validation(_)) => { }, + result => panic!("Unexpected result {:?}.", result), + } } #[test]