Hide validation stuff.
This commit is contained in:
parent
469e9ef6b1
commit
aae9a3c129
53
src/lib.rs
53
src/lib.rs
|
@ -10,10 +10,15 @@ extern crate byteorder;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error;
|
use std::error;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use parity_wasm::elements::Module;
|
||||||
|
|
||||||
/// Internal interpreter error.
|
/// Internal interpreter error.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Module validation error. Might occur only at load time.
|
||||||
|
Validation(String),
|
||||||
/// Error while instantiating a module. Might occur when provided
|
/// Error while instantiating a module. Might occur when provided
|
||||||
/// with incorrect exports (i.e. linkage failure).
|
/// with incorrect exports (i.e. linkage failure).
|
||||||
Instantiation(String),
|
Instantiation(String),
|
||||||
|
@ -38,6 +43,7 @@ pub enum Error {
|
||||||
impl Into<String> for Error {
|
impl Into<String> for Error {
|
||||||
fn into(self) -> String {
|
fn into(self) -> String {
|
||||||
match self {
|
match self {
|
||||||
|
Error::Validation(s) => s,
|
||||||
Error::Instantiation(s) => s,
|
Error::Instantiation(s) => s,
|
||||||
Error::Function(s) => s,
|
Error::Function(s) => s,
|
||||||
Error::Table(s) => s,
|
Error::Table(s) => s,
|
||||||
|
@ -54,6 +60,7 @@ impl Into<String> for Error {
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
|
Error::Validation(ref s) => write!(f, "Validation: {}", s),
|
||||||
Error::Instantiation(ref s) => write!(f, "Instantiation: {}", s),
|
Error::Instantiation(ref s) => write!(f, "Instantiation: {}", s),
|
||||||
Error::Function(ref s) => write!(f, "Function: {}", s),
|
Error::Function(ref s) => write!(f, "Function: {}", s),
|
||||||
Error::Table(ref s) => write!(f, "Table: {}", s),
|
Error::Table(ref s) => write!(f, "Table: {}", s),
|
||||||
|
@ -72,6 +79,7 @@ impl fmt::Display for Error {
|
||||||
impl error::Error for Error {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
|
Error::Validation(ref s) => s,
|
||||||
Error::Instantiation(ref s) => s,
|
Error::Instantiation(ref s) => s,
|
||||||
Error::Function(ref s) => s,
|
Error::Function(ref s) => s,
|
||||||
Error::Table(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 {
|
impl<U> From<U> for Error where U: host::HostError + Sized {
|
||||||
fn from(e: U) -> Self {
|
fn from(e: U) -> Self {
|
||||||
Error::Host(Box::new(e))
|
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 {
|
impl From<::common::stack::Error> for Error {
|
||||||
fn from(e: ::common::stack::Error) -> Self {
|
fn from(e: ::common::stack::Error) -> Self {
|
||||||
Error::Stack(e.to_string())
|
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::global::{GlobalInstance, GlobalRef};
|
||||||
pub use self::func::{FuncInstance, FuncRef};
|
pub use self::func::{FuncInstance, FuncRef};
|
||||||
pub use self::types::{Signature, ValueType};
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,13 @@ use std::fmt;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use parity_wasm::elements::{External, InitExpr, Internal, Opcode, ResizableLimits, Type};
|
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 imports::ImportResolver;
|
||||||
use global::{GlobalInstance, GlobalRef};
|
use global::{GlobalInstance, GlobalRef};
|
||||||
use func::{FuncRef, FuncBody, FuncInstance};
|
use func::{FuncRef, FuncBody, FuncInstance};
|
||||||
use table::TableRef;
|
use table::TableRef;
|
||||||
use memory::MemoryRef;
|
use memory::MemoryRef;
|
||||||
use host::Externals;
|
use host::Externals;
|
||||||
use validation::ValidatedModule;
|
|
||||||
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -158,10 +157,10 @@ impl ModuleInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_module(
|
fn alloc_module(
|
||||||
validated_module: &ValidatedModule,
|
loaded_module: &LoadedModule,
|
||||||
extern_vals: &[ExternVal]
|
extern_vals: &[ExternVal]
|
||||||
) -> Result<ModuleRef, Error> {
|
) -> Result<ModuleRef, Error> {
|
||||||
let module = validated_module.module();
|
let module = loaded_module.module();
|
||||||
let instance = ModuleRef(Rc::new(ModuleInstance::default()));
|
let instance = ModuleRef(Rc::new(ModuleInstance::default()));
|
||||||
|
|
||||||
for &Type::Function(ref ty) in module.type_section().map(|ts| ts.types()).unwrap_or(&[]) {
|
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(
|
let funcs = module.function_section().map(|fs| fs.entries()).unwrap_or(
|
||||||
&[],
|
&[],
|
||||||
|
@ -327,12 +326,12 @@ impl ModuleInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate_with_externvals(
|
fn instantiate_with_externvals(
|
||||||
validated_module: &ValidatedModule,
|
loaded_module: &LoadedModule,
|
||||||
extern_vals: &[ExternVal],
|
extern_vals: &[ExternVal],
|
||||||
) -> Result<ModuleRef, Error> {
|
) -> 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(
|
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>(
|
pub fn new<'m, I: ImportResolver>(
|
||||||
validated_module: &'m ValidatedModule,
|
loaded_module: &'m LoadedModule,
|
||||||
imports: &I,
|
imports: &I,
|
||||||
) -> Result<NotStartedModuleRef<'m>, Error> {
|
) -> Result<NotStartedModuleRef<'m>, Error> {
|
||||||
let module = validated_module.module();
|
let module = loaded_module.module();
|
||||||
|
|
||||||
let mut extern_vals = Vec::new();
|
let mut extern_vals = Vec::new();
|
||||||
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
||||||
|
@ -406,9 +405,9 @@ impl ModuleInstance {
|
||||||
extern_vals.push(extern_val);
|
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 {
|
Ok(NotStartedModuleRef {
|
||||||
validated_module,
|
loaded_module,
|
||||||
instance,
|
instance,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -439,7 +438,7 @@ impl ModuleInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NotStartedModuleRef<'a> {
|
pub struct NotStartedModuleRef<'a> {
|
||||||
validated_module: &'a ValidatedModule,
|
loaded_module: &'a LoadedModule,
|
||||||
instance: ModuleRef,
|
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> {
|
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(
|
let start_func = self.instance.func_by_index(start_fn_idx).expect(
|
||||||
"Due to validation start function should exists",
|
"Due to validation start function should exists",
|
||||||
);
|
);
|
||||||
|
@ -459,7 +458,7 @@ impl<'a> NotStartedModuleRef<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_no_start(self) -> ModuleRef {
|
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
|
self.instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
|
||||||
use parity_wasm::elements::{deserialize_buffer, MemoryType, TableType};
|
use parity_wasm::elements::{deserialize_buffer, MemoryType, TableType};
|
||||||
use validation::{validate_module, ValidatedModule};
|
|
||||||
use {
|
use {
|
||||||
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
|
Error, Signature, Externals, FuncInstance, FuncRef, HostError, ImportsBuilder,
|
||||||
MemoryInstance, MemoryRef, TableInstance, TableRef, ModuleImportResolver, ModuleInstance, ModuleRef,
|
MemoryInstance, MemoryRef, TableInstance, TableRef, ModuleImportResolver, ModuleInstance, ModuleRef,
|
||||||
RuntimeValue, TryInto,
|
RuntimeValue, TryInto, LoadedModule, load_from_buffer,
|
||||||
};
|
};
|
||||||
use types::ValueType;
|
use types::ValueType;
|
||||||
use wabt::wat2wasm;
|
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 wasm_binary = wat2wasm(source).expect("Failed to parse wat source");
|
||||||
let module = deserialize_buffer(&wasm_binary).expect("Failed to deserialize module");
|
load_from_buffer(wasm_binary).expect("Failed to load parsed module")
|
||||||
let validated_module = validate_module(module).expect("Failed to validate module");
|
|
||||||
validated_module
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use parity_wasm::elements::deserialize_file;
|
|
||||||
use parity_wasm::elements::{GlobalType, MemoryType, Module, TableType};
|
use parity_wasm::elements::{GlobalType, MemoryType, Module, TableType};
|
||||||
use {Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
|
use {
|
||||||
|
Error, Signature, FuncRef, GlobalInstance, GlobalRef, ImportsBuilder, MemoryInstance,
|
||||||
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
|
MemoryRef, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeValue,
|
||||||
TableInstance, TableRef};
|
TableInstance, TableRef, LoadedModule, load_from_buffer,
|
||||||
use validation::validate_module;
|
};
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
struct Env {
|
struct Env {
|
||||||
table_base: GlobalRef,
|
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]
|
#[test]
|
||||||
fn interpreter_inc_i32() {
|
fn interpreter_inc_i32() {
|
||||||
// Name of function contained in WASM file (note the leading underline)
|
// 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
|
// The WASM file containing the module and function
|
||||||
const WASM_FILE: &str = &"res/cases/v1/inc_i32.wasm";
|
const WASM_FILE: &str = &"res/cases/v1/inc_i32.wasm";
|
||||||
|
|
||||||
let module: Module =
|
let module = load_from_file(WASM_FILE);
|
||||||
deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
|
|
||||||
let validated_module = validate_module(module).expect("Failed to validate module");
|
|
||||||
|
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
|
|
||||||
let instance = ModuleInstance::new(
|
let instance = ModuleInstance::new(
|
||||||
&validated_module,
|
&module,
|
||||||
&ImportsBuilder::new().with_resolver("env", &env),
|
&ImportsBuilder::new().with_resolver("env", &env),
|
||||||
).expect("Failed to instantiate module")
|
).expect("Failed to instantiate module")
|
||||||
.assert_no_start();
|
.assert_no_start();
|
||||||
|
@ -110,13 +117,11 @@ fn interpreter_accumulate_u8() {
|
||||||
|
|
||||||
|
|
||||||
// Load the module-structure from wasm-file and add to program
|
// Load the module-structure from wasm-file and add to program
|
||||||
let module: Module =
|
let module = load_from_file(WASM_FILE);
|
||||||
deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
|
|
||||||
let validated_module = validate_module(module).expect("Failed to validate module");
|
|
||||||
|
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
let instance = ModuleInstance::new(
|
let instance = ModuleInstance::new(
|
||||||
&validated_module,
|
&module,
|
||||||
&ImportsBuilder::new().with_resolver("env", &env),
|
&ImportsBuilder::new().with_resolver("env", &env),
|
||||||
).expect("Failed to instantiate module")
|
).expect("Failed to instantiate module")
|
||||||
.assert_no_start();
|
.assert_no_start();
|
||||||
|
|
|
@ -38,8 +38,8 @@ impl From<stack::Error> for Error {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ValidatedModule {
|
pub struct ValidatedModule {
|
||||||
labels: HashMap<usize, HashMap<usize, usize>>,
|
pub labels: HashMap<usize, HashMap<usize, usize>>,
|
||||||
module: Module,
|
pub module: Module,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatedModule {
|
impl ValidatedModule {
|
||||||
|
@ -50,10 +50,6 @@ impl ValidatedModule {
|
||||||
pub fn into_module(self) -> Module {
|
pub fn into_module(self) -> Module {
|
||||||
self.module
|
self.module
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn labels(&self) -> &HashMap<usize, HashMap<usize, usize>> {
|
|
||||||
&self.labels
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::ops::Deref for ValidatedModule {
|
impl ::std::ops::Deref for ValidatedModule {
|
||||||
|
|
Loading…
Reference in New Issue