use alloc::{format, vec::Vec}; use core::fmt::Debug; use tracing::debug; use wasmparser::{ ExportSectionReader, FunctionBody, FunctionSectionReader, Payload, TypeSectionReader, Validator, }; use crate::{ParseError, Result}; #[derive(Default)] pub struct ModuleReader<'a> { pub version: Option, pub start_func: Option, pub type_section: Option>, pub function_section: Option>, pub export_section: Option>, pub code_section: Option>, // pub table_section: Option>, // pub memory_section: Option>, // pub global_section: Option>, // pub element_section: Option>, // pub data_section: Option>, // pub import_section: Option>, pub end_reached: bool, } impl Debug for ModuleReader<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("ModuleReader") .field("version", &self.version) .field("type_section", &self.type_section) .field("function_section", &self.function_section) .field("code_section", &self.code_section) .field("export_section", &self.export_section) // .field("table_section", &self.table_section) // .field("memory_section", &self.memory_section) // .field("global_section", &self.global_section) // .field("element_section", &self.element_section) // .field("data_section", &self.data_section) // .field("import_section", &self.import_section) .finish() } } impl<'a> ModuleReader<'a> { pub fn new() -> ModuleReader<'a> { Self::default() } pub fn process_payload( &mut self, payload: Payload<'a>, validator: &mut Validator, ) -> Result<()> { use wasmparser::Payload::*; match payload { Version { num, encoding, range, } => { validator.version(num, encoding, &range)?; self.version = Some(num); match encoding { wasmparser::Encoding::Module => {} wasmparser::Encoding::Component => { return Err(ParseError::InvalidEncoding(encoding)) } } } StartSection { func, range } => { debug!("Found start section"); validator.start_section(func, &range)?; self.start_func = Some(func); } TypeSection(reader) => { debug!("Found type section"); validator.type_section(&reader)?; self.type_section = Some(reader); } FunctionSection(reader) => { debug!("Found function section"); validator.function_section(&reader)?; self.function_section = Some(reader); } TableSection(_reader) => { return Err(ParseError::UnsupportedSection("Table section".into())); // debug!("Found table section"); // validator.table_section(&reader)?; // self.table_section = Some(reader); } MemorySection(_reader) => { return Err(ParseError::UnsupportedSection("Memory section".into())); // debug!("Found memory section"); // validator.memory_section(&reader)?; // self.memory_section = Some(reader); } GlobalSection(_reader) => { return Err(ParseError::UnsupportedSection("Global section".into())); // debug!("Found global section"); // validator.global_section(&reader)?; // self.global_section = Some(reader); } ElementSection(_reader) => { return Err(ParseError::UnsupportedSection("Element section".into())); // debug!("Found element section"); // validator.element_section(&reader)?; // self.element_section = Some(reader); } DataSection(_reader) => { return Err(ParseError::UnsupportedSection("Data section".into())); // debug!("Found data section"); // validator.data_section(&reader)?; // self.data_section = Some(reader); } CodeSectionStart { count, range, .. } => { debug!("Found code section ({} functions)", count); if self.code_section.is_some() { return Err(ParseError::DuplicateSection("Code section".into())); } validator.code_section_start(count, &range)?; self.code_section = Some(CodeSection::new()); } CodeSectionEntry(function) => { debug!("Found code section entry"); validator.code_section_entry(&function)?; if let Some(code_section) = &mut self.code_section { code_section.functions.push(function); } else { return Err(ParseError::EmptySection("Code section".into())); } } ImportSection(_reader) => { return Err(ParseError::UnsupportedSection("Import section".into())); // debug!("Found import section"); // validator.import_section(&reader)?; // self.import_section = Some(reader); } ExportSection(reader) => { debug!("Found export section"); validator.export_section(&reader)?; self.export_section = Some(reader); } End(offset) => { debug!("Reached end of module"); if self.end_reached { return Err(ParseError::DuplicateSection("End section".into())); } validator.end(offset)?; self.end_reached = true; } UnknownSection { .. } | _ => { return Err(ParseError::UnsupportedSection(format!("Unknown section"))) } }; Ok(()) } } /// A WebAssembly code section /// Can be cloned to read functions multiple times #[derive(Debug, Clone)] pub struct CodeSection<'a> { pub(crate) functions: Vec>, } impl<'a> CodeSection<'a> { fn new() -> Self { Self { functions: Vec::new(), } } }