diff options
Diffstat (limited to 'third_party/rust/wasmparser/src/readers')
22 files changed, 2802 insertions, 0 deletions
diff --git a/third_party/rust/wasmparser/src/readers/alias_section.rs b/third_party/rust/wasmparser/src/readers/alias_section.rs new file mode 100644 index 0000000000..bf64c18069 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/alias_section.rs @@ -0,0 +1,88 @@ +use crate::{ + BinaryReader, BinaryReaderError, ExternalKind, Range, Result, SectionIteratorLimited, + SectionReader, SectionWithLimitedItems, +}; + +#[derive(Clone)] +pub struct AliasSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +#[derive(Debug)] +pub struct Alias { + pub instance: AliasedInstance, + pub kind: ExternalKind, + pub index: u32, +} + +#[derive(Debug)] +pub enum AliasedInstance { + Parent, + Child(u32), +} + +impl<'a> AliasSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<AliasSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(AliasSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn read(&mut self) -> Result<Alias> { + Ok(Alias { + instance: match self.reader.read_u8()? { + 0x00 => AliasedInstance::Child(self.reader.read_var_u32()?), + 0x01 => AliasedInstance::Parent, + _ => { + return Err(BinaryReaderError::new( + "invalid byte in alias", + self.original_position() - 1, + )) + } + }, + kind: self.reader.read_external_kind()?, + index: self.reader.read_var_u32()?, + }) + } +} + +impl<'a> SectionReader for AliasSectionReader<'a> { + type Item = Alias; + + fn read(&mut self) -> Result<Self::Item> { + AliasSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + AliasSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for AliasSectionReader<'a> { + fn get_count(&self) -> u32 { + AliasSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for AliasSectionReader<'a> { + type Item = Result<Alias>; + type IntoIter = SectionIteratorLimited<AliasSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/code_section.rs b/third_party/rust/wasmparser/src/readers/code_section.rs new file mode 100644 index 0000000000..f17f66ac57 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/code_section.rs @@ -0,0 +1,238 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, BinaryReaderError, OperatorsReader, Range, Result, SectionIteratorLimited, + SectionReader, SectionWithLimitedItems, Type, +}; + +#[derive(Debug, Clone)] +pub struct FunctionBody<'a> { + offset: usize, + data: &'a [u8], +} + +impl<'a> FunctionBody<'a> { + pub fn new(offset: usize, data: &'a [u8]) -> Self { + Self { offset, data } + } + + pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b> + where + 'a: 'b, + { + BinaryReader::new_with_offset(self.data, self.offset) + } + + fn skip_locals(reader: &mut BinaryReader) -> Result<()> { + let count = reader.read_var_u32()?; + for _ in 0..count { + reader.skip_var_32()?; + reader.skip_type()?; + } + Ok(()) + } + + pub fn get_locals_reader<'b>(&self) -> Result<LocalsReader<'b>> + where + 'a: 'b, + { + let mut reader = BinaryReader::new_with_offset(self.data, self.offset); + let count = reader.read_var_u32()?; + Ok(LocalsReader { reader, count }) + } + + pub fn get_operators_reader<'b>(&self) -> Result<OperatorsReader<'b>> + where + 'a: 'b, + { + let mut reader = BinaryReader::new_with_offset(self.data, self.offset); + Self::skip_locals(&mut reader)?; + let pos = reader.position; + Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos)) + } + + pub fn range(&self) -> Range { + Range { + start: self.offset, + end: self.offset + self.data.len(), + } + } +} + +pub struct LocalsReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> LocalsReader<'a> { + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read(&mut self) -> Result<(u32, Type)> { + let count = self.reader.read_var_u32()?; + let value_type = self.reader.read_type()?; + Ok((count, value_type)) + } +} + +pub struct CodeSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> IntoIterator for LocalsReader<'a> { + type Item = Result<(u32, Type)>; + type IntoIter = LocalsIterator<'a>; + fn into_iter(self) -> Self::IntoIter { + let count = self.count; + LocalsIterator { + reader: self, + left: count, + err: false, + } + } +} + +pub struct LocalsIterator<'a> { + reader: LocalsReader<'a>, + left: u32, + err: bool, +} + +impl<'a> Iterator for LocalsIterator<'a> { + type Item = Result<(u32, Type)>; + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.left == 0 { + return None; + } + let result = self.reader.read(); + self.err = result.is_err(); + self.left -= 1; + Some(result) + } + fn size_hint(&self) -> (usize, Option<usize>) { + let count = self.reader.get_count() as usize; + (count, Some(count)) + } +} + +impl<'a> CodeSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<CodeSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(CodeSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + fn verify_body_end(&self, end: usize) -> Result<()> { + if self.reader.buffer.len() < end { + return Err(BinaryReaderError::new( + "Function body extends past end of the code section", + self.reader.original_offset + self.reader.buffer.len(), + )); + } + Ok(()) + } + + /// Reads content of the code section. + /// + /// # Examples + /// ``` + /// use wasmparser::CodeSectionReader; + /// # let data: &[u8] = &[ + /// # 0x01, 0x03, 0x00, 0x01, 0x0b]; + /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap(); + /// for _ in 0..code_reader.get_count() { + /// let body = code_reader.read().expect("function body"); + /// let mut binary_reader = body.get_binary_reader(); + /// assert!(binary_reader.read_var_u32().expect("local count") == 0); + /// let op = binary_reader.read_operator().expect("first operator"); + /// println!("First operator: {:?}", op); + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<FunctionBody<'b>> + where + 'a: 'b, + { + let size = self.reader.read_var_u32()? as usize; + let body_start = self.reader.position; + let body_end = body_start + size; + self.verify_body_end(body_end)?; + self.reader.skip_to(body_end); + Ok(FunctionBody { + offset: self.reader.original_offset + body_start, + data: &self.reader.buffer[body_start..body_end], + }) + } +} + +impl<'a> SectionReader for CodeSectionReader<'a> { + type Item = FunctionBody<'a>; + fn read(&mut self) -> Result<Self::Item> { + CodeSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + CodeSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for CodeSectionReader<'a> { + fn get_count(&self) -> u32 { + CodeSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for CodeSectionReader<'a> { + type Item = Result<FunctionBody<'a>>; + type IntoIter = SectionIteratorLimited<CodeSectionReader<'a>>; + + /// Implements iterator over the code section. + /// + /// # Examples + /// ``` + /// use wasmparser::CodeSectionReader; + /// # let data: &[u8] = &[ + /// # 0x01, 0x03, 0x00, 0x01, 0x0b]; + /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap(); + /// for body in code_reader { + /// let mut binary_reader = body.expect("b").get_binary_reader(); + /// assert!(binary_reader.read_var_u32().expect("local count") == 0); + /// let op = binary_reader.read_operator().expect("first operator"); + /// println!("First operator: {:?}", op); + /// } + /// ``` + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/data_section.rs b/third_party/rust/wasmparser/src/readers/data_section.rs new file mode 100644 index 0000000000..b9675e2de8 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/data_section.rs @@ -0,0 +1,152 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, BinaryReaderError, InitExpr, Range, Result, SectionIteratorLimited, + SectionReader, SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct Data<'a> { + pub kind: DataKind<'a>, + pub data: &'a [u8], +} + +#[derive(Debug, Copy, Clone)] +pub enum DataKind<'a> { + Passive, + Active { + memory_index: u32, + init_expr: InitExpr<'a>, + }, +} + +#[derive(Clone)] +pub struct DataSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> DataSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<DataSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(DataSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + fn verify_data_end(&self, end: usize) -> Result<()> { + if self.reader.buffer.len() < end { + return Err(BinaryReaderError::new( + "Data segment extends past end of the data section", + self.reader.original_offset + self.reader.buffer.len(), + )); + } + Ok(()) + } + + /// Reads content of the data section. + /// + /// # Examples + /// ``` + /// use wasmparser::{DataSectionReader, DataKind}; + /// # let data: &[u8] = &[ + /// # 0x01, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00]; + /// let mut data_reader = DataSectionReader::new(data, 0).unwrap(); + /// for _ in 0..data_reader.get_count() { + /// let data = data_reader.read().expect("data"); + /// println!("Data: {:?}", data); + /// if let DataKind::Active { init_expr, .. } = data.kind { + /// let mut init_expr_reader = init_expr.get_binary_reader(); + /// let op = init_expr_reader.read_operator().expect("op"); + /// println!("Init const: {:?}", op); + /// } + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<Data<'b>> + where + 'a: 'b, + { + let flags = self.reader.read_var_u32()?; + let kind = if flags == 1 { + DataKind::Passive + } else { + let memory_index = match flags { + 0 => 0, + 2 => self.reader.read_var_u32()?, + _ => { + return Err(BinaryReaderError::new( + "invalid flags byte in data segment", + self.reader.original_position() - 1, + )); + } + }; + let init_expr = { + let expr_offset = self.reader.position; + self.reader.skip_init_expr()?; + let data = &self.reader.buffer[expr_offset..self.reader.position]; + InitExpr::new(data, self.reader.original_offset + expr_offset) + }; + DataKind::Active { + memory_index, + init_expr, + } + }; + let data_len = self.reader.read_var_u32()? as usize; + let data_end = self.reader.position + data_len; + self.verify_data_end(data_end)?; + let data = &self.reader.buffer[self.reader.position..data_end]; + self.reader.skip_to(data_end); + Ok(Data { kind, data }) + } +} + +impl<'a> SectionReader for DataSectionReader<'a> { + type Item = Data<'a>; + fn read(&mut self) -> Result<Self::Item> { + DataSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + DataSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for DataSectionReader<'a> { + fn get_count(&self) -> u32 { + DataSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for DataSectionReader<'a> { + type Item = Result<Data<'a>>; + type IntoIter = SectionIteratorLimited<DataSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/element_section.rs b/third_party/rust/wasmparser/src/readers/element_section.rs new file mode 100644 index 0000000000..f01c2d1f62 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/element_section.rs @@ -0,0 +1,290 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, BinaryReaderError, InitExpr, Range, Result, SectionIteratorLimited, + SectionReader, SectionWithLimitedItems, Type, +}; +use crate::{ExternalKind, Operator}; + +#[derive(Clone)] +pub struct Element<'a> { + pub kind: ElementKind<'a>, + pub items: ElementItems<'a>, + pub ty: Type, +} + +#[derive(Clone)] +pub enum ElementKind<'a> { + Passive, + Active { + table_index: u32, + init_expr: InitExpr<'a>, + }, + Declared, +} + +#[derive(Debug, Copy, Clone)] +pub struct ElementItems<'a> { + exprs: bool, + offset: usize, + data: &'a [u8], +} + +#[derive(Debug)] +pub enum ElementItem { + Null(Type), + Func(u32), +} + +impl<'a> ElementItems<'a> { + pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>> + where + 'a: 'b, + { + ElementItemsReader::new(self.data, self.offset, self.exprs) + } +} + +pub struct ElementItemsReader<'a> { + reader: BinaryReader<'a>, + count: u32, + exprs: bool, +} + +impl<'a> ElementItemsReader<'a> { + pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ElementItemsReader { + reader, + count, + exprs, + }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn uses_exprs(&self) -> bool { + self.exprs + } + + pub fn read(&mut self) -> Result<ElementItem> { + if self.exprs { + let offset = self.reader.original_position(); + let ret = match self.reader.read_operator()? { + Operator::RefNull { ty } => ElementItem::Null(ty), + Operator::RefFunc { function_index } => ElementItem::Func(function_index), + _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), + }; + match self.reader.read_operator()? { + Operator::End => {} + _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), + } + Ok(ret) + } else { + self.reader.read_var_u32().map(ElementItem::Func) + } + } +} + +impl<'a> IntoIterator for ElementItemsReader<'a> { + type Item = Result<ElementItem>; + type IntoIter = ElementItemsIterator<'a>; + fn into_iter(self) -> Self::IntoIter { + let count = self.count; + ElementItemsIterator { + reader: self, + left: count, + err: false, + } + } +} + +pub struct ElementItemsIterator<'a> { + reader: ElementItemsReader<'a>, + left: u32, + err: bool, +} + +impl<'a> Iterator for ElementItemsIterator<'a> { + type Item = Result<ElementItem>; + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.left == 0 { + return None; + } + let result = self.reader.read(); + self.err = result.is_err(); + self.left -= 1; + Some(result) + } + fn size_hint(&self) -> (usize, Option<usize>) { + let count = self.reader.get_count() as usize; + (count, Some(count)) + } +} + +#[derive(Clone)] +pub struct ElementSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ElementSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ElementSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the element section. + /// + /// # Examples + /// + /// ```no_run + /// # let data: &[u8] = &[]; + /// use wasmparser::{ElementSectionReader, ElementKind}; + /// let mut element_reader = ElementSectionReader::new(data, 0).unwrap(); + /// for _ in 0..element_reader.get_count() { + /// let element = element_reader.read().expect("element"); + /// if let ElementKind::Active { init_expr, .. } = element.kind { + /// let mut init_expr_reader = init_expr.get_binary_reader(); + /// let op = init_expr_reader.read_operator().expect("op"); + /// println!("Init const: {:?}", op); + /// } + /// let mut items_reader = element.items.get_items_reader().expect("items reader"); + /// for _ in 0..items_reader.get_count() { + /// let item = items_reader.read().expect("item"); + /// println!(" Item: {:?}", item); + /// } + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<Element<'b>> + where + 'a: 'b, + { + let flags = self.reader.read_var_u32()?; + if (flags & !0b111) != 0 { + return Err(BinaryReaderError::new( + "invalid flags byte in element segment", + self.reader.original_position() - 1, + )); + } + let kind = if flags & 0b001 != 0 { + if flags & 0b010 != 0 { + ElementKind::Declared + } else { + ElementKind::Passive + } + } else { + let table_index = if flags & 0b010 == 0 { + 0 + } else { + self.reader.read_var_u32()? + }; + let init_expr = { + let expr_offset = self.reader.position; + self.reader.skip_init_expr()?; + let data = &self.reader.buffer[expr_offset..self.reader.position]; + InitExpr::new(data, self.reader.original_offset + expr_offset) + }; + ElementKind::Active { + table_index, + init_expr, + } + }; + let exprs = flags & 0b100 != 0; + let ty = if flags & 0b011 != 0 { + if exprs { + self.reader.read_type()? + } else { + match self.reader.read_external_kind()? { + ExternalKind::Function => Type::FuncRef, + _ => { + return Err(BinaryReaderError::new( + "only the function external type is supported in elem segment", + self.reader.original_position() - 1, + )); + } + } + } + } else { + Type::FuncRef + }; + let data_start = self.reader.position; + let items_count = self.reader.read_var_u32()?; + if exprs { + for _ in 0..items_count { + self.reader.skip_init_expr()?; + } + } else { + for _ in 0..items_count { + self.reader.skip_var_32()?; + } + } + let data_end = self.reader.position; + let items = ElementItems { + offset: self.reader.original_offset + data_start, + data: &self.reader.buffer[data_start..data_end], + exprs, + }; + Ok(Element { kind, items, ty }) + } +} + +impl<'a> SectionReader for ElementSectionReader<'a> { + type Item = Element<'a>; + fn read(&mut self) -> Result<Self::Item> { + ElementSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ElementSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> { + fn get_count(&self) -> u32 { + ElementSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ElementSectionReader<'a> { + type Item = Result<Element<'a>>; + type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/export_section.rs b/third_party/rust/wasmparser/src/readers/export_section.rs new file mode 100644 index 0000000000..4e3ff3f892 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/export_section.rs @@ -0,0 +1,102 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, ExternalKind, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct Export<'a> { + pub field: &'a str, + pub kind: ExternalKind, + pub index: u32, +} + +#[derive(Clone)] +pub struct ExportSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ExportSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<ExportSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ExportSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the export section. + /// + /// # Examples + /// ``` + /// use wasmparser::ExportSectionReader; + /// + /// # let data: &[u8] = &[0x01, 0x01, 0x65, 0x00, 0x00]; + /// let mut export_reader = ExportSectionReader::new(data, 0).unwrap(); + /// for _ in 0..export_reader.get_count() { + /// let export = export_reader.read().expect("export"); + /// println!("Export: {:?}", export); + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<Export<'b>> + where + 'a: 'b, + { + let field = self.reader.read_string()?; + let kind = self.reader.read_external_kind()?; + let index = self.reader.read_var_u32()?; + Ok(Export { field, kind, index }) + } +} + +impl<'a> SectionReader for ExportSectionReader<'a> { + type Item = Export<'a>; + fn read(&mut self) -> Result<Self::Item> { + ExportSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ExportSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ExportSectionReader<'a> { + fn get_count(&self) -> u32 { + ExportSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ExportSectionReader<'a> { + type Item = Result<Export<'a>>; + type IntoIter = SectionIteratorLimited<ExportSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/function_section.rs b/third_party/rust/wasmparser/src/readers/function_section.rs new file mode 100644 index 0000000000..0d96cf2f92 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/function_section.rs @@ -0,0 +1,88 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, Range, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, +}; + +#[derive(Clone)] +pub struct FunctionSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> FunctionSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<FunctionSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(FunctionSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads function type index from the function section. + /// + /// # Examples + /// + /// ``` + /// use wasmparser::FunctionSectionReader; + /// # let data: &[u8] = &[0x01, 0x00]; + /// let mut function_reader = FunctionSectionReader::new(data, 0).unwrap(); + /// for _ in 0..function_reader.get_count() { + /// let ty = function_reader.read().expect("function type index"); + /// println!("Function type index: {}", ty); + /// } + /// ``` + pub fn read(&mut self) -> Result<u32> { + self.reader.read_var_u32() + } +} + +impl<'a> SectionReader for FunctionSectionReader<'a> { + type Item = u32; + fn read(&mut self) -> Result<Self::Item> { + FunctionSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + FunctionSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for FunctionSectionReader<'a> { + fn get_count(&self) -> u32 { + FunctionSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for FunctionSectionReader<'a> { + type Item = Result<u32>; + type IntoIter = SectionIteratorLimited<FunctionSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/global_section.rs b/third_party/rust/wasmparser/src/readers/global_section.rs new file mode 100644 index 0000000000..fdbf75797a --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/global_section.rs @@ -0,0 +1,105 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, GlobalType, InitExpr, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct Global<'a> { + pub ty: GlobalType, + pub init_expr: InitExpr<'a>, +} + +#[derive(Clone)] +pub struct GlobalSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> GlobalSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<GlobalSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(GlobalSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the global section. + /// + /// # Examples + /// ``` + /// use wasmparser::GlobalSectionReader; + /// # let data: &[u8] = &[0x01, 0x7F, 0x01, 0x41, 0x90, 0x88, 0x04, 0x0B]; + /// let mut global_reader = GlobalSectionReader::new(data, 0).unwrap(); + /// for _ in 0..global_reader.get_count() { + /// let global = global_reader.read().expect("global"); + /// println!("Global: {:?}", global); + /// let mut init_expr_reader = global.init_expr.get_binary_reader(); + /// let op = init_expr_reader.read_operator().expect("op"); + /// println!("Init const: {:?}", op); + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<Global<'b>> + where + 'a: 'b, + { + let ty = self.reader.read_global_type()?; + let expr_offset = self.reader.position; + self.reader.skip_init_expr()?; + let data = &self.reader.buffer[expr_offset..self.reader.position]; + let init_expr = InitExpr::new(data, self.reader.original_offset + expr_offset); + Ok(Global { ty, init_expr }) + } +} + +impl<'a> SectionReader for GlobalSectionReader<'a> { + type Item = Global<'a>; + fn read(&mut self) -> Result<Self::Item> { + GlobalSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + GlobalSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for GlobalSectionReader<'a> { + fn get_count(&self) -> u32 { + GlobalSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for GlobalSectionReader<'a> { + type Item = Result<Global<'a>>; + type IntoIter = SectionIteratorLimited<GlobalSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/import_section.rs b/third_party/rust/wasmparser/src/readers/import_section.rs new file mode 100644 index 0000000000..4f75bcfe86 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/import_section.rs @@ -0,0 +1,98 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::{ + BinaryReader, ImportSectionEntryType, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct Import<'a> { + pub module: &'a str, + pub field: Option<&'a str>, + pub ty: ImportSectionEntryType, +} + +#[derive(Clone)] +pub struct ImportSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ImportSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<ImportSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ImportSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the import section. + /// + /// # Examples + /// ``` + /// use wasmparser::ImportSectionReader; + /// # let data: &[u8] = &[0x01, 0x01, 0x41, 0x01, 0x66, 0x00, 0x00]; + /// let mut import_reader = ImportSectionReader::new(data, 0).unwrap(); + /// for _ in 0..import_reader.get_count() { + /// let import = import_reader.read().expect("import"); + /// println!("Import: {:?}", import); + /// } + /// ``` + pub fn read<'b>(&mut self) -> Result<Import<'b>> + where + 'a: 'b, + { + self.reader.read_import() + } +} + +impl<'a> SectionReader for ImportSectionReader<'a> { + type Item = Import<'a>; + fn read(&mut self) -> Result<Self::Item> { + ImportSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ImportSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ImportSectionReader<'a> { + fn get_count(&self) -> u32 { + ImportSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ImportSectionReader<'a> { + type Item = Result<Import<'a>>; + type IntoIter = SectionIteratorLimited<ImportSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/init_expr.rs b/third_party/rust/wasmparser/src/readers/init_expr.rs new file mode 100644 index 0000000000..98c301d350 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/init_expr.rs @@ -0,0 +1,42 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{BinaryReader, OperatorsReader}; + +#[derive(Debug, Copy, Clone)] +pub struct InitExpr<'a> { + offset: usize, + data: &'a [u8], +} + +impl<'a> InitExpr<'a> { + pub fn new(data: &[u8], offset: usize) -> InitExpr { + InitExpr { offset, data } + } + + pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b> + where + 'a: 'b, + { + BinaryReader::new_with_offset(self.data, self.offset) + } + + pub fn get_operators_reader<'b>(&self) -> OperatorsReader<'b> + where + 'a: 'b, + { + OperatorsReader::new(self.data, self.offset) + } +} diff --git a/third_party/rust/wasmparser/src/readers/instance_section.rs b/third_party/rust/wasmparser/src/readers/instance_section.rs new file mode 100644 index 0000000000..5c27954044 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/instance_section.rs @@ -0,0 +1,162 @@ +use crate::{ + BinaryReader, BinaryReaderError, ExternalKind, Range, Result, SectionIteratorLimited, + SectionReader, SectionWithLimitedItems, +}; + +#[derive(Clone)] +pub struct InstanceSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> InstanceSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<InstanceSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(InstanceSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn read(&mut self) -> Result<Instance<'a>> { + let instance = Instance::new( + &self.reader.buffer[self.reader.position..], + self.original_position(), + )?; + self.reader.skip_bytes(1)?; + self.reader.skip_var_32()?; + let count = self.reader.read_var_u32()?; + for _ in 0..count { + self.reader.skip_bytes(1)?; + self.reader.skip_var_32()?; + } + Ok(instance) + } +} + +impl<'a> SectionReader for InstanceSectionReader<'a> { + type Item = Instance<'a>; + + fn read(&mut self) -> Result<Self::Item> { + InstanceSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + InstanceSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for InstanceSectionReader<'a> { + fn get_count(&self) -> u32 { + InstanceSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for InstanceSectionReader<'a> { + type Item = Result<Instance<'a>>; + type IntoIter = SectionIteratorLimited<InstanceSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} + +pub struct Instance<'a> { + reader: BinaryReader<'a>, + module: u32, +} + +impl<'a> Instance<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<Instance<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + if reader.read_u8()? != 0 { + return Err(BinaryReaderError::new( + "instantiate instruction not found", + offset, + )); + } + let module = reader.read_var_u32()?; + Ok(Instance { module, reader }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn module(&self) -> u32 { + self.module + } + + pub fn args(&self) -> Result<InstanceArgsReader<'a>> { + let mut reader = self.reader.clone(); + let count = reader.read_var_u32()?; + Ok(InstanceArgsReader { + count, + remaining: count, + reader, + }) + } +} + +#[derive(Clone)] +pub struct InstanceArgsReader<'a> { + reader: BinaryReader<'a>, + count: u32, + remaining: u32, +} + +impl<'a> InstanceArgsReader<'a> { + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read(&mut self) -> Result<(ExternalKind, u32)> { + let kind = self.reader.read_external_kind()?; + let index = self.reader.read_var_u32()?; + self.remaining -= 1; + Ok((kind, index)) + } +} + +impl<'a> SectionReader for InstanceArgsReader<'a> { + type Item = (ExternalKind, u32); + + fn read(&mut self) -> Result<Self::Item> { + InstanceArgsReader::read(self) + } + fn eof(&self) -> bool { + self.remaining == 0 + } + fn original_position(&self) -> usize { + InstanceArgsReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for InstanceArgsReader<'a> { + fn get_count(&self) -> u32 { + self.count + } +} + +impl<'a> IntoIterator for InstanceArgsReader<'a> { + type Item = Result<(ExternalKind, u32)>; + type IntoIter = SectionIteratorLimited<InstanceArgsReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/linking_section.rs b/third_party/rust/wasmparser/src/readers/linking_section.rs new file mode 100644 index 0000000000..4b999744f0 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/linking_section.rs @@ -0,0 +1,78 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, LinkingType, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +pub struct LinkingSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> LinkingSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<LinkingSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(LinkingSectionReader { reader, count }) + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read<'b>(&mut self) -> Result<LinkingType> + where + 'a: 'b, + { + Ok(self.reader.read_linking_type()?) + } +} + +impl<'a> SectionReader for LinkingSectionReader<'a> { + type Item = LinkingType; + fn read(&mut self) -> Result<Self::Item> { + LinkingSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + LinkingSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for LinkingSectionReader<'a> { + fn get_count(&self) -> u32 { + LinkingSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for LinkingSectionReader<'a> { + type Item = Result<LinkingType>; + type IntoIter = SectionIteratorLimited<LinkingSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/memory_section.rs b/third_party/rust/wasmparser/src/readers/memory_section.rs new file mode 100644 index 0000000000..b84a59dff1 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/memory_section.rs @@ -0,0 +1,88 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, MemoryType, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +#[derive(Clone)] +pub struct MemorySectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> MemorySectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<MemorySectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(MemorySectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the memory section. + /// + /// # Examples + /// ``` + /// use wasmparser::MemorySectionReader; + /// # let data: &[u8] = &[0x01, 0x00, 0x02]; + /// let mut memory_reader = MemorySectionReader::new(data, 0).unwrap(); + /// for _ in 0..memory_reader.get_count() { + /// let memory = memory_reader.read().expect("memory"); + /// println!("Memory: {:?}", memory); + /// } + /// ``` + pub fn read(&mut self) -> Result<MemoryType> { + self.reader.read_memory_type() + } +} + +impl<'a> SectionReader for MemorySectionReader<'a> { + type Item = MemoryType; + fn read(&mut self) -> Result<Self::Item> { + MemorySectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + MemorySectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for MemorySectionReader<'a> { + fn get_count(&self) -> u32 { + MemorySectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for MemorySectionReader<'a> { + type Item = Result<MemoryType>; + type IntoIter = SectionIteratorLimited<MemorySectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/mod.rs b/third_party/rust/wasmparser/src/readers/mod.rs new file mode 100644 index 0000000000..9cf8bf1a81 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/mod.rs @@ -0,0 +1,63 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, BinaryReaderError, ExternalKind, GlobalType, LinkingType, MemoryType, NameType, + Naming, Operator, Range, RelocType, Result, SectionCode, TableType, Type, +}; + +pub use self::alias_section::*; +pub use self::code_section::*; +pub use self::data_section::*; +pub use self::element_section::*; +pub use self::export_section::*; +pub use self::function_section::*; +pub use self::global_section::*; +pub use self::import_section::*; +pub use self::init_expr::*; +pub use self::instance_section::*; +pub use self::linking_section::*; +pub use self::memory_section::*; +pub use self::module_code_section::*; +pub use self::module_section::*; +pub use self::name_section::*; +pub use self::operators::*; +pub use self::producers_section::*; +pub use self::reloc_section::*; +pub use self::section_reader::*; +pub use self::table_section::*; +pub use self::type_section::*; + +mod alias_section; +mod code_section; +mod data_section; +mod element_section; +mod export_section; +mod function_section; +mod global_section; +mod import_section; +mod init_expr; +mod instance_section; +mod linking_section; +mod memory_section; +mod module_code_section; +mod module_section; +mod name_section; +mod operators; +mod producers_section; +mod reloc_section; +mod section_reader; +mod table_section; +mod type_section; diff --git a/third_party/rust/wasmparser/src/readers/module_code_section.rs b/third_party/rust/wasmparser/src/readers/module_code_section.rs new file mode 100644 index 0000000000..866cd443af --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/module_code_section.rs @@ -0,0 +1,96 @@ +use crate::{ + BinaryReader, BinaryReaderError, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +pub struct ModuleCodeSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +#[derive(Debug)] +pub struct ModuleCode<'a> { + reader: BinaryReader<'a>, +} + +impl<'a> ModuleCodeSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<ModuleCodeSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ModuleCodeSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + fn verify_module_end(&self, end: usize) -> Result<()> { + if self.reader.buffer.len() < end { + return Err(BinaryReaderError::new( + "module body extends past end of the module code section", + self.reader.original_offset + self.reader.buffer.len(), + )); + } + Ok(()) + } + + pub fn read(&mut self) -> Result<ModuleCode<'a>> { + let size = self.reader.read_var_u32()? as usize; + let module_start = self.reader.position; + let module_end = module_start + size; + self.verify_module_end(module_end)?; + self.reader.skip_to(module_end); + Ok(ModuleCode { + reader: BinaryReader::new_with_offset( + &self.reader.buffer[module_start..module_end], + self.reader.original_offset + module_start, + ), + }) + } +} + +impl<'a> SectionReader for ModuleCodeSectionReader<'a> { + type Item = ModuleCode<'a>; + + fn read(&mut self) -> Result<Self::Item> { + ModuleCodeSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ModuleCodeSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ModuleCodeSectionReader<'a> { + fn get_count(&self) -> u32 { + ModuleCodeSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ModuleCodeSectionReader<'a> { + type Item = Result<ModuleCode<'a>>; + type IntoIter = SectionIteratorLimited<ModuleCodeSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} + +impl<'a> ModuleCode<'a> { + pub fn raw_bytes(&self) -> (usize, &[u8]) { + (self.reader.original_position(), self.reader.buffer) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } +} diff --git a/third_party/rust/wasmparser/src/readers/module_section.rs b/third_party/rust/wasmparser/src/readers/module_section.rs new file mode 100644 index 0000000000..86b73f7a7f --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/module_section.rs @@ -0,0 +1,61 @@ +use super::{ + BinaryReader, Range, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, +}; + +#[derive(Clone)] +pub struct ModuleSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ModuleSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<ModuleSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ModuleSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn read(&mut self) -> Result<u32> { + self.reader.read_var_u32() + } +} + +impl<'a> SectionReader for ModuleSectionReader<'a> { + type Item = u32; + + fn read(&mut self) -> Result<Self::Item> { + ModuleSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ModuleSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ModuleSectionReader<'a> { + fn get_count(&self) -> u32 { + ModuleSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ModuleSectionReader<'a> { + type Item = Result<u32>; + type IntoIter = SectionIteratorLimited<ModuleSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/name_section.rs b/third_party/rust/wasmparser/src/readers/name_section.rs new file mode 100644 index 0000000000..343a7441ab --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/name_section.rs @@ -0,0 +1,253 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, BinaryReaderError, NameType, Naming, Range, Result, SectionIterator, + SectionReader, +}; + +#[derive(Debug, Copy, Clone)] +pub struct ModuleName<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> ModuleName<'a> { + pub fn get_name<'b>(&self) -> Result<&'b str> + where + 'a: 'b, + { + let mut reader = BinaryReader::new_with_offset(self.data, self.offset); + reader.read_string() + } + + pub fn original_position(&self) -> usize { + self.offset + } +} + +pub struct NamingReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> NamingReader<'a> { + fn new(data: &'a [u8], offset: usize) -> Result<NamingReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(NamingReader { reader, count }) + } + + fn skip(reader: &mut BinaryReader) -> Result<()> { + let count = reader.read_var_u32()?; + for _ in 0..count { + reader.skip_var_32()?; + reader.skip_string()?; + } + Ok(()) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn read<'b>(&mut self) -> Result<Naming<'b>> + where + 'a: 'b, + { + let index = self.reader.read_var_u32()?; + let name = self.reader.read_string()?; + Ok(Naming { index, name }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct FunctionName<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> FunctionName<'a> { + pub fn get_map<'b>(&self) -> Result<NamingReader<'b>> + where + 'a: 'b, + { + NamingReader::new(self.data, self.offset) + } + + pub fn original_position(&self) -> usize { + self.offset + } +} + +#[derive(Debug, Copy, Clone)] +pub struct FunctionLocalName<'a> { + pub func_index: u32, + data: &'a [u8], + offset: usize, +} + +impl<'a> FunctionLocalName<'a> { + pub fn get_map<'b>(&self) -> Result<NamingReader<'b>> + where + 'a: 'b, + { + NamingReader::new(self.data, self.offset) + } + + pub fn original_position(&self) -> usize { + self.offset + } +} + +pub struct FunctionLocalReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> FunctionLocalReader<'a> { + fn new(data: &'a [u8], offset: usize) -> Result<FunctionLocalReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(FunctionLocalReader { reader, count }) + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read<'b>(&mut self) -> Result<FunctionLocalName<'b>> + where + 'a: 'b, + { + let func_index = self.reader.read_var_u32()?; + let start = self.reader.position; + NamingReader::skip(&mut self.reader)?; + let end = self.reader.position; + Ok(FunctionLocalName { + func_index, + data: &self.reader.buffer[start..end], + offset: self.reader.original_offset + start, + }) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct LocalName<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> LocalName<'a> { + pub fn get_function_local_reader<'b>(&self) -> Result<FunctionLocalReader<'b>> + where + 'a: 'b, + { + FunctionLocalReader::new(self.data, self.offset) + } + + pub fn original_position(&self) -> usize { + self.offset + } +} + +#[derive(Debug, Copy, Clone)] +pub enum Name<'a> { + Module(ModuleName<'a>), + Function(FunctionName<'a>), + Local(LocalName<'a>), +} + +pub struct NameSectionReader<'a> { + reader: BinaryReader<'a>, +} + +impl<'a> NameSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<NameSectionReader<'a>> { + Ok(NameSectionReader { + reader: BinaryReader::new_with_offset(data, offset), + }) + } + + fn verify_section_end(&self, end: usize) -> Result<()> { + if self.reader.buffer.len() < end { + return Err(BinaryReaderError::new( + "Name entry extends past end of the code section", + self.reader.original_offset + self.reader.buffer.len(), + )); + } + Ok(()) + } + + pub fn eof(&self) -> bool { + self.reader.eof() + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read<'b>(&mut self) -> Result<Name<'b>> + where + 'a: 'b, + { + let ty = self.reader.read_name_type()?; + let payload_len = self.reader.read_var_u32()? as usize; + let payload_start = self.reader.position; + let payload_end = payload_start + payload_len; + self.verify_section_end(payload_end)?; + let offset = self.reader.original_offset + payload_start; + let data = &self.reader.buffer[payload_start..payload_end]; + self.reader.skip_to(payload_end); + Ok(match ty { + NameType::Module => Name::Module(ModuleName { data, offset }), + NameType::Function => Name::Function(FunctionName { data, offset }), + NameType::Local => Name::Local(LocalName { data, offset }), + }) + } +} + +impl<'a> SectionReader for NameSectionReader<'a> { + type Item = Name<'a>; + fn read(&mut self) -> Result<Self::Item> { + NameSectionReader::read(self) + } + fn eof(&self) -> bool { + NameSectionReader::eof(self) + } + fn original_position(&self) -> usize { + NameSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> IntoIterator for NameSectionReader<'a> { + type Item = Result<Name<'a>>; + type IntoIter = SectionIterator<NameSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIterator::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/operators.rs b/third_party/rust/wasmparser/src/readers/operators.rs new file mode 100644 index 0000000000..cda42571dd --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/operators.rs @@ -0,0 +1,161 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{BinaryReader, BinaryReaderError, Operator, Result}; + +#[derive(Clone)] +pub struct OperatorsReader<'a> { + pub(crate) reader: BinaryReader<'a>, +} + +impl<'a> OperatorsReader<'a> { + pub(crate) fn new<'b>(data: &'a [u8], offset: usize) -> OperatorsReader<'b> + where + 'a: 'b, + { + OperatorsReader { + reader: BinaryReader::new_with_offset(data, offset), + } + } + + pub fn eof(&self) -> bool { + self.reader.eof() + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn ensure_end(&self) -> Result<()> { + if self.eof() { + return Ok(()); + } + Err(BinaryReaderError::new( + "Unexpected data at the end of operators", + self.reader.original_position(), + )) + } + + pub fn read<'b>(&mut self) -> Result<Operator<'b>> + where + 'a: 'b, + { + self.reader.read_operator() + } + + pub fn into_iter_with_offsets<'b>(self) -> OperatorsIteratorWithOffsets<'b> + where + 'a: 'b, + { + OperatorsIteratorWithOffsets { + reader: self, + err: false, + } + } + + pub fn read_with_offset<'b>(&mut self) -> Result<(Operator<'b>, usize)> + where + 'a: 'b, + { + let pos = self.reader.original_position(); + Ok((self.read()?, pos)) + } +} + +impl<'a> IntoIterator for OperatorsReader<'a> { + type Item = Result<Operator<'a>>; + type IntoIter = OperatorsIterator<'a>; + + /// Reads content of the code section. + /// + /// # Examples + /// ``` + /// use wasmparser::{Operator, CodeSectionReader, Result}; + /// # let data: &[u8] = &[ + /// # 0x01, 0x03, 0x00, 0x01, 0x0b]; + /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap(); + /// for _ in 0..code_reader.get_count() { + /// let body = code_reader.read().expect("function body"); + /// let mut op_reader = body.get_operators_reader().expect("op reader"); + /// let ops = op_reader.into_iter().collect::<Result<Vec<Operator>>>().expect("ops"); + /// assert!( + /// if let [Operator::Nop, Operator::End] = ops.as_slice() { true } else { false }, + /// "found {:?}", + /// ops + /// ); + /// } + /// ``` + fn into_iter(self) -> Self::IntoIter { + OperatorsIterator { + reader: self, + err: false, + } + } +} + +pub struct OperatorsIterator<'a> { + reader: OperatorsReader<'a>, + err: bool, +} + +impl<'a> Iterator for OperatorsIterator<'a> { + type Item = Result<Operator<'a>>; + + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.reader.eof() { + return None; + } + let result = self.reader.read(); + self.err = result.is_err(); + Some(result) + } +} + +pub struct OperatorsIteratorWithOffsets<'a> { + reader: OperatorsReader<'a>, + err: bool, +} + +impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> { + type Item = Result<(Operator<'a>, usize)>; + + /// Reads content of the code section with offsets. + /// + /// # Examples + /// ``` + /// use wasmparser::{Operator, CodeSectionReader, Result}; + /// # let data: &[u8] = &[ + /// # 0x01, 0x03, 0x00, /* offset = 23 */ 0x01, 0x0b]; + /// let mut code_reader = CodeSectionReader::new(data, 20).unwrap(); + /// for _ in 0..code_reader.get_count() { + /// let body = code_reader.read().expect("function body"); + /// let mut op_reader = body.get_operators_reader().expect("op reader"); + /// let ops = op_reader.into_iter_with_offsets().collect::<Result<Vec<(Operator, usize)>>>().expect("ops"); + /// assert!( + /// if let [(Operator::Nop, 23), (Operator::End, 24)] = ops.as_slice() { true } else { false }, + /// "found {:?}", + /// ops + /// ); + /// } + /// ``` + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.reader.eof() { + return None; + } + let result = self.reader.read_with_offset(); + self.err = result.is_err(); + Some(result) + } +} diff --git a/third_party/rust/wasmparser/src/readers/producers_section.rs b/third_party/rust/wasmparser/src/readers/producers_section.rs new file mode 100644 index 0000000000..d6a9051b16 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/producers_section.rs @@ -0,0 +1,197 @@ +/* Copyright 2019 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, Range, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct ProducersFieldValue<'a> { + pub name: &'a str, + pub version: &'a str, +} + +pub struct ProducersFieldValuesReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ProducersFieldValuesReader<'a> { + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + fn skip(reader: &mut BinaryReader, values_count: u32) -> Result<()> { + for _ in 0..values_count { + reader.skip_string()?; + reader.skip_string()?; + } + Ok(()) + } + + pub fn read<'b>(&mut self) -> Result<ProducersFieldValue<'b>> + where + 'a: 'b, + { + let name = self.reader.read_string()?; + let version = self.reader.read_string()?; + Ok(ProducersFieldValue { name, version }) + } +} + +impl<'a> IntoIterator for ProducersFieldValuesReader<'a> { + type Item = Result<ProducersFieldValue<'a>>; + type IntoIter = ProducersFieldValuesIterator<'a>; + fn into_iter(self) -> Self::IntoIter { + let count = self.count; + ProducersFieldValuesIterator { + reader: self, + left: count, + err: false, + } + } +} + +pub struct ProducersFieldValuesIterator<'a> { + reader: ProducersFieldValuesReader<'a>, + left: u32, + err: bool, +} + +impl<'a> Iterator for ProducersFieldValuesIterator<'a> { + type Item = Result<ProducersFieldValue<'a>>; + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.left == 0 { + return None; + } + let result = self.reader.read(); + self.err = result.is_err(); + self.left -= 1; + Some(result) + } + fn size_hint(&self) -> (usize, Option<usize>) { + let count = self.reader.get_count() as usize; + (count, Some(count)) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct ProducersField<'a> { + pub name: &'a str, + values_count: u32, + values_data: &'a [u8], + values_offset: usize, +} + +impl<'a> ProducersField<'a> { + pub fn get_producer_field_values_reader<'b>(&self) -> Result<ProducersFieldValuesReader<'b>> + where + 'a: 'b, + { + Ok(ProducersFieldValuesReader { + reader: BinaryReader::new_with_offset(self.values_data, self.values_offset), + count: self.values_count, + }) + } +} + +pub struct ProducersSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> ProducersSectionReader<'a> { + /// Creates reader for the producers section. + /// + /// # Examples + /// ``` + /// # let data: &[u8] = &[0x01, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, + /// # 0x02, 0x03, 0x77, 0x61, 0x74, 0x01, 0x31, 0x01, 0x43, 0x03, 0x39, 0x2e, 0x30]; + /// use wasmparser::{ProducersSectionReader, ProducersFieldValue, Result}; + /// let mut reader = ProducersSectionReader::new(data, 0).expect("producers reader"); + /// let field = reader.read().expect("producers field"); + /// assert!(field.name == "language"); + /// let mut values_reader = field.get_producer_field_values_reader().expect("values reader"); + /// let value = values_reader.into_iter().collect::<Result<Vec<ProducersFieldValue>>>().expect("values"); + /// assert!(value.len() == 2); + /// assert!(value[0].name == "wat" && value[0].version == "1"); + /// assert!(value[1].name == "C" && value[1].version == "9.0"); + /// ``` + pub fn new(data: &'a [u8], offset: usize) -> Result<ProducersSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(ProducersSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn read<'b>(&mut self) -> Result<ProducersField<'b>> + where + 'a: 'b, + { + let name = self.reader.read_string()?; + let values_count = self.reader.read_var_u32()?; + let values_start = self.reader.position; + ProducersFieldValuesReader::skip(&mut self.reader, values_count)?; + let values_end = self.reader.position; + Ok(ProducersField { + name, + values_count, + values_data: &self.reader.buffer[values_start..values_end], + values_offset: self.reader.original_offset + values_start, + }) + } +} + +impl<'a> SectionReader for ProducersSectionReader<'a> { + type Item = ProducersField<'a>; + fn read(&mut self) -> Result<Self::Item> { + ProducersSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + ProducersSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for ProducersSectionReader<'a> { + fn get_count(&self) -> u32 { + ProducersSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for ProducersSectionReader<'a> { + type Item = Result<ProducersField<'a>>; + type IntoIter = SectionIteratorLimited<ProducersSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/reloc_section.rs b/third_party/rust/wasmparser/src/readers/reloc_section.rs new file mode 100644 index 0000000000..b390ff90b6 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/reloc_section.rs @@ -0,0 +1,118 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, Range, RelocType, Result, SectionCode, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, +}; + +#[derive(Debug, Copy, Clone)] +pub struct Reloc { + pub ty: RelocType, + pub offset: u32, + pub index: u32, + pub addend: Option<u32>, +} + +pub struct RelocSectionReader<'a> { + reader: BinaryReader<'a>, + section_code: SectionCode<'a>, + count: u32, +} + +impl<'a> RelocSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<RelocSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + + let section_id_position = reader.position; + let section_id = reader.read_var_u7()?; + let section_code = reader.read_section_code(section_id, section_id_position)?; + + let count = reader.read_var_u32()?; + Ok(RelocSectionReader { + reader, + section_code, + count, + }) + } + + pub fn get_count(&self) -> u32 { + self.count + } + + pub fn get_section_code<'b>(&self) -> SectionCode<'b> + where + 'a: 'b, + { + self.section_code + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn read(&mut self) -> Result<Reloc> { + let ty = self.reader.read_reloc_type()?; + let offset = self.reader.read_var_u32()?; + let index = self.reader.read_var_u32()?; + let addend = match ty { + RelocType::FunctionIndexLEB + | RelocType::TableIndexSLEB + | RelocType::TableIndexI32 + | RelocType::TypeIndexLEB + | RelocType::GlobalIndexLEB => None, + RelocType::GlobalAddrLEB | RelocType::GlobalAddrSLEB | RelocType::GlobalAddrI32 => { + Some(self.reader.read_var_u32()?) + } + }; + Ok(Reloc { + ty, + offset, + index, + addend, + }) + } +} + +impl<'a> SectionReader for RelocSectionReader<'a> { + type Item = Reloc; + fn read(&mut self) -> Result<Self::Item> { + RelocSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + RelocSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for RelocSectionReader<'a> { + fn get_count(&self) -> u32 { + RelocSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for RelocSectionReader<'a> { + type Item = Result<Reloc>; + type IntoIter = SectionIteratorLimited<RelocSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/section_reader.rs b/third_party/rust/wasmparser/src/readers/section_reader.rs new file mode 100644 index 0000000000..395c1a2fd4 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/section_reader.rs @@ -0,0 +1,124 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{BinaryReaderError, Range, Result}; + +pub trait SectionReader { + type Item; + fn read(&mut self) -> Result<Self::Item>; + fn eof(&self) -> bool; + fn original_position(&self) -> usize; + fn range(&self) -> Range; + fn ensure_end(&self) -> Result<()> { + if self.eof() { + return Ok(()); + } + Err(BinaryReaderError::new( + "Unexpected data at the end of the section", + self.original_position(), + )) + } +} + +pub trait SectionWithLimitedItems { + fn get_count(&self) -> u32; +} + +pub struct SectionIterator<R> +where + R: SectionReader, +{ + reader: R, + err: bool, +} + +impl<R> SectionIterator<R> +where + R: SectionReader, +{ + pub fn new(reader: R) -> SectionIterator<R> { + SectionIterator { reader, err: false } + } +} + +impl<R> Iterator for SectionIterator<R> +where + R: SectionReader, +{ + type Item = Result<R::Item>; + + fn next(&mut self) -> Option<Self::Item> { + if self.err || self.reader.eof() { + return None; + } + let result = self.reader.read(); + self.err = result.is_err(); + Some(result) + } +} + +pub struct SectionIteratorLimited<R> +where + R: SectionReader + SectionWithLimitedItems, +{ + reader: R, + left: u32, + end: bool, +} + +impl<R> SectionIteratorLimited<R> +where + R: SectionReader + SectionWithLimitedItems, +{ + pub fn new(reader: R) -> SectionIteratorLimited<R> { + let left = reader.get_count(); + SectionIteratorLimited { + reader, + left, + end: false, + } + } +} + +impl<R> Iterator for SectionIteratorLimited<R> +where + R: SectionReader + SectionWithLimitedItems, +{ + type Item = Result<R::Item>; + + fn next(&mut self) -> Option<Self::Item> { + if self.end { + return None; + } + if self.left == 0 { + return match self.reader.ensure_end() { + Ok(()) => None, + Err(err) => { + self.end = true; + Some(Err(err)) + } + }; + } + let result = self.reader.read(); + self.end = result.is_err(); + self.left -= 1; + Some(result) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let count = self.reader.get_count() as usize; + (count, Some(count)) + } +} diff --git a/third_party/rust/wasmparser/src/readers/table_section.rs b/third_party/rust/wasmparser/src/readers/table_section.rs new file mode 100644 index 0000000000..40fb4942ee --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/table_section.rs @@ -0,0 +1,89 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use super::{ + BinaryReader, Range, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, + TableType, +}; + +#[derive(Clone)] +pub struct TableSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> TableSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<TableSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(TableSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the table section. + /// + /// # Examples + /// ``` + /// use wasmparser::TableSectionReader; + /// + /// # let data: &[u8] = &[0x01, 0x70, 0x01, 0x01, 0x01]; + /// let mut table_reader = TableSectionReader::new(data, 0).unwrap(); + /// for _ in 0..table_reader.get_count() { + /// let table = table_reader.read().expect("table"); + /// println!("Table: {:?}", table); + /// } + /// ``` + pub fn read(&mut self) -> Result<TableType> { + self.reader.read_table_type() + } +} + +impl<'a> SectionReader for TableSectionReader<'a> { + type Item = TableType; + fn read(&mut self) -> Result<Self::Item> { + TableSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + TableSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for TableSectionReader<'a> { + fn get_count(&self) -> u32 { + TableSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for TableSectionReader<'a> { + type Item = Result<TableType>; + type IntoIter = SectionIteratorLimited<TableSectionReader<'a>>; + + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} diff --git a/third_party/rust/wasmparser/src/readers/type_section.rs b/third_party/rust/wasmparser/src/readers/type_section.rs new file mode 100644 index 0000000000..addd756727 --- /dev/null +++ b/third_party/rust/wasmparser/src/readers/type_section.rs @@ -0,0 +1,109 @@ +/* Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::{ + BinaryReader, BinaryReaderError, Range, Result, SectionIteratorLimited, SectionReader, + SectionWithLimitedItems, TypeDef, +}; + +#[derive(Clone)] +pub struct TypeSectionReader<'a> { + reader: BinaryReader<'a>, + count: u32, +} + +impl<'a> TypeSectionReader<'a> { + pub fn new(data: &'a [u8], offset: usize) -> Result<TypeSectionReader<'a>> { + let mut reader = BinaryReader::new_with_offset(data, offset); + let count = reader.read_var_u32()?; + Ok(TypeSectionReader { reader, count }) + } + + pub fn original_position(&self) -> usize { + self.reader.original_position() + } + + pub fn get_count(&self) -> u32 { + self.count + } + + /// Reads content of the type section. + /// + /// # Examples + /// ``` + /// use wasmparser::TypeSectionReader; + /// # let data: &[u8] = &[0x01, 0x60, 0x00, 0x00]; + /// let mut type_reader = TypeSectionReader::new(data, 0).unwrap(); + /// for _ in 0..type_reader.get_count() { + /// let ty = type_reader.read().expect("type"); + /// println!("Type {:?}", ty); + /// } + /// ``` + pub fn read(&mut self) -> Result<TypeDef<'a>> { + Ok(match self.reader.read_u8()? { + 0x60 => TypeDef::Func(self.reader.read_func_type()?), + 0x61 => TypeDef::Module(self.reader.read_module_type()?), + 0x62 => TypeDef::Instance(self.reader.read_instance_type()?), + _ => { + return Err(BinaryReaderError::new( + "invalid leading byte in type definition", + self.original_position() - 1, + )) + } + }) + } +} + +impl<'a> SectionReader for TypeSectionReader<'a> { + type Item = TypeDef<'a>; + fn read(&mut self) -> Result<Self::Item> { + TypeSectionReader::read(self) + } + fn eof(&self) -> bool { + self.reader.eof() + } + fn original_position(&self) -> usize { + TypeSectionReader::original_position(self) + } + fn range(&self) -> Range { + self.reader.range() + } +} + +impl<'a> SectionWithLimitedItems for TypeSectionReader<'a> { + fn get_count(&self) -> u32 { + TypeSectionReader::get_count(self) + } +} + +impl<'a> IntoIterator for TypeSectionReader<'a> { + type Item = Result<TypeDef<'a>>; + type IntoIter = SectionIteratorLimited<TypeSectionReader<'a>>; + + /// Implements iterator over the type section. + /// + /// # Examples + /// ``` + /// use wasmparser::TypeSectionReader; + /// # let data: &[u8] = &[0x01, 0x60, 0x00, 0x00]; + /// let mut type_reader = TypeSectionReader::new(data, 0).unwrap(); + /// for ty in type_reader { + /// println!("Type {:?}", ty); + /// } + /// ``` + fn into_iter(self) -> Self::IntoIter { + SectionIteratorLimited::new(self) + } +} |