summaryrefslogtreecommitdiff
path: root/crates/parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser')
-rw-r--r--crates/parser/src/conversion.rs64
-rw-r--r--crates/parser/src/error.rs2
-rw-r--r--crates/parser/src/lib.rs20
-rw-r--r--crates/parser/src/module.rs10
-rw-r--r--crates/parser/src/visit.rs7
5 files changed, 76 insertions, 27 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 487f992..8a12daa 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -3,7 +3,7 @@ use alloc::sync::Arc;
use crate::{Result, module::FunctionCode, visit::process_operators_and_validate};
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use tinywasm_types::*;
-use wasmparser::{FuncValidator, FuncValidatorAllocations, OperatorsReader, ValidatorResources};
+use wasmparser::{CompositeInnerType, FuncValidator, FuncValidatorAllocations, OperatorsReader, ValidatorResources};
pub(crate) fn convert_module_elements<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Element<'a>>>>(
elements: T,
@@ -39,7 +39,7 @@ pub(crate) fn convert_module_element(element: wasmparser::Element<'_>) -> Result
.collect::<Result<Vec<_>>>()?
.into_boxed_slice();
- Ok(tinywasm_types::Element { kind, items, ty: convert_reftype(ty), range: element.range })
+ Ok(tinywasm_types::Element { kind, items, ty: convert_reftype(ty)?, range: element.range })
}
}
}
@@ -74,7 +74,7 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result<Im
let kind = match import.ty {
wasmparser::TypeRef::Func(ty) => ImportKind::Function(ty),
wasmparser::TypeRef::Table(ty) => ImportKind::Table(TableType {
- element_type: convert_reftype(ty.element_type),
+ element_type: convert_reftype(ty.element_type)?,
size_initial: ty.initial.try_into().map_err(|_| {
crate::ParseError::UnsupportedOperator(format!("Table size initial is too large: {}", ty.initial))
})?,
@@ -87,7 +87,7 @@ pub(crate) fn convert_module_import(import: wasmparser::Import<'_>) -> Result<Im
}),
wasmparser::TypeRef::Memory(ty) => ImportKind::Memory(convert_module_memory(ty)),
wasmparser::TypeRef::Global(ty) => {
- ImportKind::Global(GlobalType::new(convert_valtype(&ty.content_type), ty.mutable))
+ ImportKind::Global(GlobalType::new(convert_valtype(&ty.content_type)?, ty.mutable))
}
wasmparser::TypeRef::Tag(ty) => {
return Err(crate::ParseError::UnsupportedOperator(format!("Unsupported import kind: {ty:?}")));
@@ -129,7 +129,7 @@ pub(crate) fn convert_module_table(table: wasmparser::Table<'_>) -> Result<Table
let size_max = table.ty.maximum.map(|max| max.try_into()).transpose();
let size_max =
size_max.map_err(|e| crate::ParseError::UnsupportedOperator(format!("Table size max is too large: {e}")))?;
- Ok(TableType { element_type: convert_reftype(table.ty.element_type), size_initial, size_max })
+ Ok(TableType { element_type: convert_reftype(table.ty.element_type)?, size_initial, size_max })
}
pub(crate) fn convert_module_globals(
@@ -139,7 +139,7 @@ pub(crate) fn convert_module_globals(
.into_iter()
.map(|global| {
let global = global?;
- let ty = convert_valtype(&global.ty.content_type);
+ let ty = convert_valtype(&global.ty.content_type)?;
let ops = global.init_expr.get_operators_reader();
Ok(Global { init: process_const_operators(ops)?, ty: GlobalType::new(ty, global.ty.mutable) })
})
@@ -211,27 +211,37 @@ pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<Arc<FuncTy
));
}
- let ty = types.next().unwrap().unwrap_func();
+ let ty = types.next().unwrap();
+ let CompositeInnerType::Func(ty) = &ty.composite_type.inner else {
+ return Err(crate::ParseError::UnsupportedOperator(format!(
+ "Unsupported non-function type in type section: {}",
+ ty.composite_type
+ )));
+ };
let params: Vec<_> = ty.params().iter().map(convert_valtype).collect();
- let results: Vec<_> = ty.results().iter().map(convert_valtype).collect();
+ let params = params.into_iter().collect::<Result<Vec<_>>>()?;
+ let results = ty.results().iter().map(convert_valtype).collect::<Result<Vec<_>>>()?;
Ok(FuncType::new(&params, &results).into())
}
-pub(crate) fn convert_reftype(reftype: wasmparser::RefType) -> WasmType {
+pub(crate) fn convert_reftype(reftype: wasmparser::RefType) -> Result<WasmType> {
match reftype {
- _ if reftype.is_func_ref() => WasmType::RefFunc,
- _ if reftype.is_extern_ref() => WasmType::RefExtern,
- _ => unimplemented!("Unsupported reference type: {:?}, {:?}", reftype, reftype.heap_type()),
+ _ if reftype.is_func_ref() => Ok(WasmType::RefFunc),
+ _ if reftype.is_extern_ref() => Ok(WasmType::RefExtern),
+ _ => Err(crate::ParseError::UnsupportedOperator(format!(
+ "Unsupported reference type: {reftype:?}, {:?}",
+ reftype.heap_type()
+ ))),
}
}
-pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> WasmType {
+pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> Result<WasmType> {
match valtype {
- wasmparser::ValType::I32 => WasmType::I32,
- wasmparser::ValType::I64 => WasmType::I64,
- wasmparser::ValType::F32 => WasmType::F32,
- wasmparser::ValType::F64 => WasmType::F64,
- wasmparser::ValType::V128 => WasmType::V128,
+ wasmparser::ValType::I32 => Ok(WasmType::I32),
+ wasmparser::ValType::I64 => Ok(WasmType::I64),
+ wasmparser::ValType::F32 => Ok(WasmType::F32),
+ wasmparser::ValType::F64 => Ok(WasmType::F64),
+ wasmparser::ValType::V128 => Ok(WasmType::V128),
wasmparser::ValType::Ref(r) => convert_reftype(*r),
}
}
@@ -247,10 +257,14 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<Box<[C
let mut out = Vec::with_capacity(ops.len().saturating_sub(1));
for op in ops.iter().take(ops.len() - 1) {
let instr = match op {
- wasmparser::Operator::RefNull { hty } => match convert_heaptype(*hty) {
+ wasmparser::Operator::RefNull { hty } => match convert_heaptype(*hty)? {
WasmType::RefFunc => ConstInstruction::RefFunc(None),
WasmType::RefExtern => ConstInstruction::RefExtern(None),
- _ => unimplemented!("Unsupported heap type: {:?}", hty),
+ other => {
+ return Err(crate::ParseError::UnsupportedOperator(format!(
+ "Unsupported ref.null heap type lowered to {other:?}"
+ )));
+ }
},
wasmparser::Operator::RefFunc { function_index } => ConstInstruction::RefFunc(Some(*function_index)),
wasmparser::Operator::I32Const { value } => ConstInstruction::I32Const(*value),
@@ -277,12 +291,14 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<Box<[C
Ok(out.into_boxed_slice())
}
-pub(crate) fn convert_heaptype(heap: wasmparser::HeapType) -> WasmType {
+pub(crate) fn convert_heaptype(heap: wasmparser::HeapType) -> Result<WasmType> {
match heap {
- wasmparser::HeapType::Abstract { shared: false, ty: wasmparser::AbstractHeapType::Func } => WasmType::RefFunc,
+ wasmparser::HeapType::Abstract { shared: false, ty: wasmparser::AbstractHeapType::Func } => {
+ Ok(WasmType::RefFunc)
+ }
wasmparser::HeapType::Abstract { shared: false, ty: wasmparser::AbstractHeapType::Extern } => {
- WasmType::RefExtern
+ Ok(WasmType::RefExtern)
}
- _ => unimplemented!("Unsupported heap type: {:?}", heap),
+ _ => Err(crate::ParseError::UnsupportedOperator(format!("Unsupported heap type: {heap:?}"))),
}
}
diff --git a/crates/parser/src/error.rs b/crates/parser/src/error.rs
index 22edd39..7b5dc34 100644
--- a/crates/parser/src/error.rs
+++ b/crates/parser/src/error.rs
@@ -2,7 +2,7 @@ use alloc::string::{String, ToString};
use core::fmt::{Debug, Display};
use wasmparser::Encoding;
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
/// Errors that can occur when parsing a WebAssembly module
pub enum ParseError {
/// An invalid type was encountered
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index c4f6ff7..c6ae326 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -283,7 +283,25 @@ impl Parser {
continue;
}
- if eof || reader.end_reached {
+ if reader.end_reached {
+ if !buffer.is_empty() {
+ return Err(ParseError::Other("trailing bytes after end of module".into()));
+ }
+
+ if !eof {
+ let read_bytes = Self::read_more(&mut stream, &mut buffer, 1)?;
+ eof = read_bytes == 0;
+
+ if !eof {
+ return Err(ParseError::Other("trailing bytes after end of module".into()));
+ }
+ }
+
+ reader.process_pending_functions(&self.options)?;
+ return reader.into_module(&self.options);
+ }
+
+ if eof {
reader.process_pending_functions(&self.options)?;
return reader.into_module(&self.options);
}
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index 02a3297..5f5e5e2 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -377,6 +377,15 @@ impl<'a> ModuleReader<'a> {
};
let mut funcs = Vec::with_capacity(self.code.len());
+ let mut func_type_idxs = self
+ .imports
+ .iter()
+ .filter_map(|import| match import.kind {
+ ImportKind::Function(type_idx) => Some(type_idx),
+ _ => None,
+ })
+ .collect::<Vec<_>>();
+ func_type_idxs.extend(self.code_type_addrs.iter().copied());
for (code, ty_idx) in self.code.into_iter().zip(self.code_type_addrs) {
let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone();
@@ -402,6 +411,7 @@ impl<'a> ModuleReader<'a> {
Ok(ModuleInner {
funcs: funcs.into(),
func_types: self.func_types.into(),
+ func_type_idxs: func_type_idxs.into(),
globals: self.globals.into(),
table_types: self.table_types.into(),
imports: self.imports.into(),
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index f8d5cfd..62db307 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -417,7 +417,12 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
// Reference Types
fn visit_ref_null(&mut self, ty: wasmparser::HeapType) -> Self::Output {
- self.instructions.push(Instruction::RefNull(convert_heaptype(ty)));
+ match convert_heaptype(ty) {
+ Ok(ty) => self.instructions.push(Instruction::RefNull(ty)),
+ Err(err) => {
+ self.error.get_or_insert(err);
+ }
+ };
}
fn visit_typed_select_multi(&mut self, tys: Vec<wasmparser::ValType>) -> Self::Output {