diff --git a/src/validation/func.rs b/src/validation/func.rs index e459c0c..9388b30 100644 --- a/src/validation/func.rs +++ b/src/validation/func.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use elements::{Opcode, BlockType, ValueType, TableElementType}; use elements::{FunctionType, Type}; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; -use validation::module::ValidatedModule; +use validation::module::ModuleContext; use validation::Error; @@ -17,7 +17,7 @@ const NATURAL_ALIGNMENT: u32 = 0xFFFFFFFF; /// Function validation context. pub struct FunctionValidationContext<'a> { /// Wasm module - module: &'a ValidatedModule, + module: &'a ModuleContext, /// Current instruction position. position: usize, /// Local variables. @@ -546,7 +546,7 @@ impl Validator { impl<'a> FunctionValidationContext<'a> { pub fn new( - module: &'a ValidatedModule, + module: &'a ModuleContext, locals: &'a [ValueType], value_stack_limit: usize, frame_stack_limit: usize, @@ -721,20 +721,15 @@ impl<'a> FunctionValidationContext<'a> { } pub fn require_function(&self, idx: u32) -> Result<(Vec, BlockType), Error> { - let ty = match self.module.function_types().get(idx as usize) { - Some(&Type::Function(ref func_ty)) => func_ty, + let ty_idx = match self.module.func_type_indexes().get(idx as usize) { + Some(ty_idx) => *ty_idx, None => { return Err(Error( format!("Function at index {} doesn't exists", idx), )); } }; - - let params = ty.params().to_vec(); - let return_ty = ty.return_type() - .map(BlockType::Value) - .unwrap_or(BlockType::NoResult); - Ok((params, return_ty)) + self.require_function_type(ty_idx) } pub fn require_function_type(&self, idx: u32) -> Result<(Vec, BlockType), Error> { diff --git a/src/validation/mod.rs b/src/validation/mod.rs index 5cc680d..959358c 100644 --- a/src/validation/mod.rs +++ b/src/validation/mod.rs @@ -4,8 +4,9 @@ mod module; mod func; use std::fmt; -use elements::{Module, ResizableLimits, MemoryType, TableType}; +use elements::{Module, ResizableLimits, MemoryType, TableType, GlobalType, External}; use common::stack; +use self::module::ModuleContext; pub struct Error(String); @@ -22,8 +23,6 @@ impl From for Error { } pub fn validate_module(module: &Module) -> Result<(), Error> { - // TODO: Functions - if let Some(table_section) = module.table_section() { table_section .entries() @@ -43,6 +42,43 @@ pub fn validate_module(module: &Module) -> Result<(), Error> { Ok(()) } +fn prepare_context(module: &Module) -> ModuleContext { + // Copy types from module as is. + let types = module + .type_section() + .map(|ts| ts.types().into_iter().cloned().collect()) + .unwrap_or_default(); + + // Fill elements with imported values. + let mut func_type_indexes = Vec::new(); + let mut tables = Vec::new(); + let mut memories = Vec::new(); + let mut globals = Vec::new(); + + for import_entry in module + .import_section() + .map(|i| i.entries()) + .unwrap_or_default() + { + match import_entry.external() { + &External::Function(idx) => func_type_indexes.push(idx), + &External::Table(ref table) => tables.push(table.clone()), + &External::Memory(ref memory) => memories.push(memory.clone()), + &External::Global(ref global) => globals.push(global.clone()), + } + } + + // Concatenate elements with defined in the module. + + ModuleContext { + types, + tables, + memories, + globals, + func_type_indexes, + } +} + impl ResizableLimits { fn validate(&self) -> Result<(), Error> { if let Some(maximum) = self.maximum() { diff --git a/src/validation/module.rs b/src/validation/module.rs index abe65aa..af11f45 100644 --- a/src/validation/module.rs +++ b/src/validation/module.rs @@ -1,26 +1,31 @@ use elements::{MemoryType, TableType, GlobalType, Type}; -pub struct ValidatedModule { +pub struct ModuleContext { + pub memories: Vec, + pub tables: Vec, + pub globals: Vec, + pub types: Vec, + pub func_type_indexes: Vec, } -impl ValidatedModule { +impl ModuleContext { pub fn memories(&self) -> &[MemoryType] { - unimplemented!(); + &self.memories } pub fn tables(&self) -> &[TableType] { - unimplemented!(); + &self.tables } pub fn globals(&self) -> &[GlobalType] { - unimplemented!(); + &self.globals } pub fn types(&self) -> &[Type] { - unimplemented!(); + &self.types } - pub fn function_types(&self) -> &[Type] { - unimplemented!(); + pub fn func_type_indexes(&self) -> &[u32] { + &self.func_type_indexes } }