diff --git a/lib/execute/src/action.rs b/lib/execute/src/action.rs index 0194bf495a..5afbd08929 100644 --- a/lib/execute/src/action.rs +++ b/lib/execute/src/action.rs @@ -119,6 +119,10 @@ pub enum ActionError { #[fail(display = "Type error: {}", _0)] Type(String), + /// The module did not pass validation. + #[fail(display = "Validation error: {}", _0)] + Validate(String), + /// A wasm translation error occured. #[fail(display = "WebAssembly compilation error: {}", _0)] Compile(CompileError), diff --git a/lib/wast/Cargo.toml b/lib/wast/Cargo.toml index 4562b500d0..774dcc3085 100644 --- a/lib/wast/Cargo.toml +++ b/lib/wast/Cargo.toml @@ -21,6 +21,7 @@ wabt = "0.7" target-lexicon = "0.2.0" failure = { version = "0.1.3", default-features = false } failure_derive = { version = "0.1.3", default-features = false } +wasmparser = { git = "https://github.com/sunfishcode/wasmparser.rs", branch = "export-operator-validator-config" } [badges] maintenance = { status = "experimental" } diff --git a/lib/wast/src/lib.rs b/lib/wast/src/lib.rs index fc56cee98b..d986b30764 100644 --- a/lib/wast/src/lib.rs +++ b/lib/wast/src/lib.rs @@ -31,6 +31,7 @@ extern crate failure; extern crate failure_derive; extern crate target_lexicon; extern crate wabt; +extern crate wasmparser; extern crate wasmtime_environ; extern crate wasmtime_execute; extern crate wasmtime_runtime; diff --git a/lib/wast/src/wast.rs b/lib/wast/src/wast.rs index 5289183a17..f82d1575ae 100644 --- a/lib/wast/src/wast.rs +++ b/lib/wast/src/wast.rs @@ -6,6 +6,7 @@ use std::io::Read; use std::path::Path; use std::{fmt, fs, io, str}; use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value}; +use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig}; use wasmtime_execute::{ActionError, ActionOutcome, InstancePlus, JITCode, Resolver, RuntimeValue}; use wasmtime_runtime::Export; @@ -121,17 +122,35 @@ impl WastContext { } } + fn validate(&mut self, data: &[u8]) -> Result<(), ActionError> { + let config = ValidatingParserConfig { + operator_config: OperatorValidatorConfig { + enable_threads: false, + enable_reference_types: false, + }, + mutable_global_imports: true, + }; + + // TODO: Fix Cranelift to be able to perform validation itself, rather + // than calling into wasmparser ourselves here. + if validate(data, Some(config)) { + Ok(()) + } else { + // TODO: Work with wasmparser to get better error messages. + Err(ActionError::Validate("module did not validate".to_owned())) + } + } + fn instantiate( &mut self, isa: &isa::TargetIsa, module: ModuleBinary, ) -> Result { - InstancePlus::new( - &mut self.jit_code, - isa, - &module.into_vec(), - &mut self.namespace, - ) + let data = module.into_vec(); + + self.validate(&data)?; + + InstancePlus::new(&mut self.jit_code, isa, &data, &mut self.namespace) } fn get_instance(&mut self, module: &Option) -> Result { @@ -465,17 +484,25 @@ impl WastContext { } } } - CommandKind::AssertInvalid { - module: _module, - message: _message, - } => { - println!("{}:{}: TODO: Implement assert_invalid", filename, line); + CommandKind::AssertInvalid { module, message } => { + self.module(isa, None, module).expect_err(&format!( + "{}:{}: invalid module was successfully instantiated", + filename, line + )); + println!( + "{}:{}: TODO: Check the assert_invalid message: {}", + filename, line, message + ); } - CommandKind::AssertMalformed { - module: _module, - message: _message, - } => { - println!("{}:{}: TODO: Implement assert_malformed", filename, line); + CommandKind::AssertMalformed { module, message } => { + self.module(isa, None, module).expect_err(&format!( + "{}:{}: malformed module was successfully instantiated", + filename, line + )); + println!( + "{}:{}: TODO: Check the assert_malformed message: {}", + filename, line, message + ); } CommandKind::AssertUninstantiable { module, message } => { let _err = self.module(isa, None, module).expect_err(&format!(