Skip to content

Commit

Permalink
wasmpaser: Validate nested modules
Browse files Browse the repository at this point in the history
This commit implements recursive validation of nested modules in
wasmparser. Previously nested modules were simply skipped but now
they're recursed into and actually checked. This commit also comes with
a more complete implementation of handling `alias` directives.

Internally this required quite a bit of refactoring. The validator now
retains a stack of modules which are being validated and remembers
parent-relationships between them. Indices into this stack are then used
for recording type definitions. The type of a
function/instance/module/etc can be defined the current module or any
previous module on the stack. New helper functiosn were added to help
resolve this new `Def` type to ensure it's handled correctly.
  • Loading branch information
alexcrichton committed Jun 29, 2020
1 parent 5fd8bb4 commit f75a496
Show file tree
Hide file tree
Showing 10 changed files with 627 additions and 355 deletions.
6 changes: 3 additions & 3 deletions crates/wasmparser/src/module_resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ pub trait WasmModuleResources {
/// Returns the global variable at given index.
fn global_at(&self, at: u32) -> Option<&Self::GlobalType>;
/// Returns the function signature ID at given index.
fn func_type_id_at(&self, at: u32) -> Option<u32>;
fn func_type_at(&self, at: u32) -> Option<&<Self::TypeDef as WasmTypeDef>::FuncType>;
/// Returns the element type at the given index.
fn element_type_at(&self, at: u32) -> Option<crate::Type>;

Expand Down Expand Up @@ -336,8 +336,8 @@ where
fn global_at(&self, at: u32) -> Option<&Self::GlobalType> {
T::global_at(self, at)
}
fn func_type_id_at(&self, at: u32) -> Option<u32> {
T::func_type_id_at(self, at)
fn func_type_at(&self, at: u32) -> Option<&<T::TypeDef as WasmTypeDef>::FuncType> {
T::func_type_at(self, at)
}
fn element_type_at(&self, at: u32) -> Option<crate::Type> {
T::element_type_at(self, at)
Expand Down
5 changes: 2 additions & 3 deletions crates/wasmparser/src/operators_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ impl OperatorValidator {
function_index: u32,
resources: impl WasmModuleResources,
) -> OperatorValidatorResult<()> {
let type_index = match resources.func_type_id_at(function_index) {
let ty = match resources.func_type_at(function_index) {
Some(i) => i,
None => {
bail_op_err!(
Expand All @@ -532,7 +532,6 @@ impl OperatorValidator {
);
}
};
let ty = func_type_at(&resources, type_index)?;
self.check_operands(wasm_func_type_inputs(ty).map(WasmType::to_parser_type))?;
self.func_state.change_frame_with_types(
ty.len_inputs(),
Expand Down Expand Up @@ -1557,7 +1556,7 @@ impl OperatorValidator {
}
Operator::RefFunc { function_index } => {
self.check_reference_types_enabled()?;
if resources.func_type_id_at(function_index).is_none() {
if resources.func_type_at(function_index).is_none() {
return Err(OperatorValidatorError::new(
"unknown function: function index out of bounds",
));
Expand Down
17 changes: 17 additions & 0 deletions crates/wasmparser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1294,3 +1294,20 @@ impl<'a> WasmDecoder<'a> for Parser<'a> {
&self.state
}
}

impl<'a> From<ModuleReader<'a>> for Parser<'a> {
fn from(reader: ModuleReader<'a>) -> Parser<'a> {
let mut parser = Parser::default();
parser.state = ParserState::BeginWasm {
version: reader.get_version(),
};
parser.module_reader = Some(reader);
return parser;
}
}

impl<'a> Default for Parser<'a> {
fn default() -> Parser<'a> {
Parser::new(&[])
}
}
Loading

0 comments on commit f75a496

Please sign in to comment.