Hide validation stuff.

This commit is contained in:
Sergey Pepyakin 2018-01-22 16:11:20 +03:00
parent 469e9ef6b1
commit aae9a3c129
5 changed files with 90 additions and 40 deletions

View File

@ -10,10 +10,15 @@ extern crate byteorder;
use std::fmt;
use std::error;
use std::path::Path;
use std::collections::HashMap;
use parity_wasm::elements::Module;
/// Internal interpreter error.
#[derive(Debug)]
pub enum Error {
/// Module validation error. Might occur only at load time.
Validation(String),
/// Error while instantiating a module. Might occur when provided
/// with incorrect exports (i.e. linkage failure).
Instantiation(String),
@ -38,6 +43,7 @@ pub enum Error {
impl Into<String> for Error {
fn into(self) -> String {
match self {
Error::Validation(s) => s,
Error::Instantiation(s) => s,
Error::Function(s) => s,
Error::Table(s) => s,
@ -54,6 +60,7 @@ impl Into<String> for Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Validation(ref s) => write!(f, "Validation: {}", s),
Error::Instantiation(ref s) => write!(f, "Instantiation: {}", s),
Error::Function(ref s) => write!(f, "Function: {}", s),
Error::Table(ref s) => write!(f, "Table: {}", s),
@ -72,6 +79,7 @@ impl fmt::Display for Error {
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Validation(ref s) => s,
Error::Instantiation(ref s) => s,
Error::Function(ref s) => s,
Error::Table(ref s) => s,
@ -85,12 +93,19 @@ impl error::Error for Error {
}
}
impl<U> From<U> for Error where U: host::HostError + Sized {
fn from(e: U) -> Self {
Error::Host(Box::new(e))
}
}
impl From<validation::Error> for Error {
fn from(e: validation::Error) -> Error {
Error::Validation(e.to_string())
}
}
impl From<::common::stack::Error> for Error {
fn from(e: ::common::stack::Error) -> Self {
Error::Stack(e.to_string())
@ -122,3 +137,41 @@ pub use self::module::{ModuleInstance, ModuleRef, ExternVal, NotStartedModuleRef
pub use self::global::{GlobalInstance, GlobalRef};
pub use self::func::{FuncInstance, FuncRef};
pub use self::types::{Signature, ValueType};
pub struct LoadedModule {
labels: HashMap<usize, HashMap<usize, usize>>,
module: Module,
}
impl LoadedModule {
pub(crate) fn module(&self) -> &Module {
&self.module
}
pub(crate) fn labels(&self) -> &HashMap<usize, HashMap<usize, usize>> {
&self.labels
}
pub fn into_module(self) -> Module {
self.module
}
}
pub fn load_from_module(module: Module) -> Result<LoadedModule, Error> {
use validation::{validate_module, ValidatedModule};
let ValidatedModule {
labels,
module,
} = validate_module(module)?;
Ok(LoadedModule {
labels,
module,
})
}
pub fn load_from_buffer<B: AsRef<[u8]>>(buffer: B) -> Result<LoadedModule, Error> {
let module = parity_wasm::elements::deserialize_buffer(buffer.as_ref())
.map_err(|e: parity_wasm::elements::Error| Error::Validation(e.to_string()))?;
load_from_module(module)
}

View File

@ -4,14 +4,13 @@ use std::fmt;
use std::collections::HashMap;
use std::borrow::Cow;
use parity_wasm::elements::{External, InitExpr, Internal, Opcode, ResizableLimits, Type};
use {Error, Signature, MemoryInstance, RuntimeValue, TableInstance};
use {LoadedModule, Error, Signature, MemoryInstance, RuntimeValue, TableInstance};
use imports::ImportResolver;
use global::{GlobalInstance, GlobalRef};
use func::{FuncRef, FuncBody, FuncInstance};
use table::TableRef;
use memory::MemoryRef;
use host::Externals;
use validation::ValidatedModule;
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
#[derive(Clone, Debug)]
@ -158,10 +157,10 @@ impl ModuleInstance {
}
fn alloc_module(
validated_module: &ValidatedModule,
loaded_module: &LoadedModule,
extern_vals: &[ExternVal]
) -> Result<ModuleRef, Error> {
let module = validated_module.module();
let module = loaded_module.module();
let instance = ModuleRef(Rc::new(ModuleInstance::default()));
for &Type::Function(ref ty) in module.type_section().map(|ts| ts.types()).unwrap_or(&[]) {
@ -227,7 +226,7 @@ impl ModuleInstance {
}
}
let labels = validated_module.labels();
let labels = loaded_module.labels();
{
let funcs = module.function_section().map(|fs| fs.entries()).unwrap_or(
&[],
@ -327,12 +326,12 @@ impl ModuleInstance {
}
fn instantiate_with_externvals(
validated_module: &ValidatedModule,
loaded_module: &LoadedModule,
extern_vals: &[ExternVal],
) -> Result<ModuleRef, Error> {
let module = validated_module.module();
let module = loaded_module.module();
let module_ref = ModuleInstance::alloc_module(validated_module, extern_vals)?;
let module_ref = ModuleInstance::alloc_module(loaded_module, extern_vals)?;
for element_segment in module.elements_section().map(|es| es.entries()).unwrap_or(
&[],
@ -371,10 +370,10 @@ impl ModuleInstance {
}
pub fn new<'m, I: ImportResolver>(
validated_module: &'m ValidatedModule,
loaded_module: &'m LoadedModule,
imports: &I,
) -> Result<NotStartedModuleRef<'m>, Error> {
let module = validated_module.module();
let module = loaded_module.module();
let mut extern_vals = Vec::new();
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
@ -406,9 +405,9 @@ impl ModuleInstance {
extern_vals.push(extern_val);
}
let instance = Self::instantiate_with_externvals(validated_module, &extern_vals)?;
let instance = Self::instantiate_with_externvals(loaded_module, &extern_vals)?;
Ok(NotStartedModuleRef {
validated_module,
loaded_module,
instance,
})
}
@ -439,7 +438,7 @@ impl ModuleInstance {
}
pub struct NotStartedModuleRef<'a> {
validated_module: &'a ValidatedModule,
loaded_module: &'a LoadedModule,
instance: ModuleRef,
}
@ -449,7 +448,7 @@ impl<'a> NotStartedModuleRef<'a> {
}
pub fn run_start<'b, E: Externals>(self, state: &'b mut E) -> Result<ModuleRef, Error> {
if let Some(start_fn_idx) = self.validated_module.module().start_section() {
if let Some(start_fn_idx) = self.loaded_module.module().start_section() {
let start_func = self.instance.func_by_index(start_fn_idx).expect(
"Due to validation start function should exists",
);
@ -459,7 +458,7 @@ impl<'a> NotStartedModuleRef<'a> {
}
pub fn assert_no_start(self) -> ModuleRef {
assert!(self.validated_module.module().start_section().is_none());
assert!(self.loaded_module.module().start_section().is_none());
self.instance
}
}

View File

@ -1,10 +1,9 @@
use parity_wasm::elements::{deserialize_buffer, MemoryType, TableType};
use validation::{validate_module, ValidatedModule};
use {
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
MemoryInstance, MemoryRef, TableInstance, TableRef, ModuleImportResolver, ModuleInstance, ModuleRef,
RuntimeValue, TryInto,
RuntimeValue, TryInto, LoadedModule, load_from_buffer,
};
use types::ValueType;
use wabt::wat2wasm;
@ -204,11 +203,9 @@ impl ModuleImportResolver for TestHost {
}
}
fn parse_wat(source: &str) -> ValidatedModule {
fn parse_wat(source: &str) -> LoadedModule {
let wasm_binary = wat2wasm(source).expect("Failed to parse wat source");
let module = deserialize_buffer(&wasm_binary).expect("Failed to deserialize module");
let validated_module = validate_module(module).expect("Failed to validate module");
validated_module
load_from_buffer(wasm_binary).expect("Failed to load parsed module")
}
#[test]

View File

@ -1,9 +1,10 @@
use parity_wasm::elements::deserialize_file;
use parity_wasm::elements::{GlobalType, MemoryType, Module, TableType};
use {Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
TableInstance, TableRef};
use validation::validate_module;
use {
Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
TableInstance, TableRef, LoadedModule, load_from_buffer,
};
use std::fs::File;
struct Env {
table_base: GlobalRef,
@ -69,6 +70,14 @@ impl ModuleImportResolver for Env {
}
}
fn load_from_file(filename: &str) -> LoadedModule {
use std::io::prelude::*;
let mut file = File::open(filename).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
load_from_buffer(buf).unwrap()
}
#[test]
fn interpreter_inc_i32() {
// Name of function contained in WASM file (note the leading underline)
@ -76,14 +85,12 @@ fn interpreter_inc_i32() {
// The WASM file containing the module and function
const WASM_FILE: &str = &"res/cases/v1/inc_i32.wasm";
let module: Module =
deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
let validated_module = validate_module(module).expect("Failed to validate module");
let module = load_from_file(WASM_FILE);
let env = Env::new();
let instance = ModuleInstance::new(
&validated_module,
&module,
&ImportsBuilder::new().with_resolver("env", &env),
).expect("Failed to instantiate module")
.assert_no_start();
@ -110,13 +117,11 @@ fn interpreter_accumulate_u8() {
// Load the module-structure from wasm-file and add to program
let module: Module =
deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
let validated_module = validate_module(module).expect("Failed to validate module");
let module = load_from_file(WASM_FILE);
let env = Env::new();
let instance = ModuleInstance::new(
&validated_module,
&module,
&ImportsBuilder::new().with_resolver("env", &env),
).expect("Failed to instantiate module")
.assert_no_start();

View File

@ -38,8 +38,8 @@ impl From<stack::Error> for Error {
#[derive(Clone)]
pub struct ValidatedModule {
labels: HashMap<usize, HashMap<usize, usize>>,
module: Module,
pub labels: HashMap<usize, HashMap<usize, usize>>,
pub module: Module,
}
impl ValidatedModule {
@ -50,10 +50,6 @@ impl ValidatedModule {
pub fn into_module(self) -> Module {
self.module
}
pub(crate) fn labels(&self) -> &HashMap<usize, HashMap<usize, usize>> {
&self.labels
}
}
impl ::std::ops::Deref for ValidatedModule {