From 22189e23048e9891486d56e2b41e0c2b27ba6f21 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 13:24:46 +0200 Subject: [PATCH 1/9] add BrTable2 and BrTableBuilder --- src/lib.rs | 2 ++ src/primitives.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e581b932..96fb359b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,6 +38,8 @@ pub use crate::parser::WasmDecoder; pub use crate::primitives::BinaryReaderError; pub use crate::primitives::BrTable; +pub use crate::primitives::BrTable2; +pub use crate::primitives::BrTableBuilder; pub use crate::primitives::CustomSectionKind; pub use crate::primitives::ExternalKind; pub use crate::primitives::FuncType; diff --git a/src/primitives.rs b/src/primitives.rs index d55dd350..6cf6ecac 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -219,6 +219,85 @@ pub struct BrTable<'a> { pub(crate) cnt: usize, } +/// A branch table (`br_table`). +/// +/// Stores its target and default branch offsets. +#[derive(Debug, Clone)] +pub struct BrTable2 { + /// Non-empty vector storing the target offsets followed by the default offset. + targets: Vec, +} + +impl BrTable2 { + /// Creates a new branch table builder. + pub fn new() -> BrTableBuilder { + BrTableBuilder::default() + } + + /// Returns an iterator over the non-default branching targets. + pub fn non_default_targets<'a>(&'a self) -> impl Iterator + 'a { + self.targets.iter().copied() + } + + /// Returns an iterator over the branching targets. + pub fn targets(&self) -> core::slice::Iter { + self.targets.iter() + } + + /// Returns the number of non-default branch targets. + pub fn len_non_default_targets(&self) -> usize { + self.targets.len().saturating_sub(1) + } + + /// Returns the number of branch target. + pub fn len_targets(&self) -> usize { + self.targets.len() + } + + /// Returns the default branch offset. + pub fn default_offset(&self) -> u32 { + self.targets.last().copied().expect("targets list is empty") + } +} + +/// A builder for a branch table (`br_table`). +#[derive(Debug)] +pub struct BrTableBuilder { + /// The building branch table. + br_table: BrTable2, +} + +impl Default for BrTableBuilder { + fn default() -> Self { + Self { br_table: BrTable2 { targets: Vec::new() } } + } +} + +impl BrTableBuilder { + /// Pushes another branching target to the branch table. + pub fn push_target(mut self, target: u32) -> Self { + self.br_table.targets.push(target); + self + } + + /// Pushes the given branching targets to the branch table. + pub fn push_targets(mut self, targets: I) -> Self + where + I: IntoIterator, + { + for target in targets { + self.br_table.targets.push(target); + } + self + } + + /// Finalizes the branch table with the given default branching offset. + pub fn default_target(mut self, default_target: u32) -> BrTable2 { + self.br_table.targets.push(default_target); + self.br_table + } +} + /// An IEEE binary32 immediate floating point value, represented as a u32 /// containing the bitpattern. /// From c74ec3ee9d6c8c7e4b227fb0fb73f4df73ac7feb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 14:50:06 +0200 Subject: [PATCH 2/9] introduce WasmBrTable and WasmBrTableBuilder traits --- src/primitives.rs | 103 ++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/src/primitives.rs b/src/primitives.rs index 6cf6ecac..54530ba7 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -219,44 +219,64 @@ pub struct BrTable<'a> { pub(crate) cnt: usize, } +/// Trait implemented by Wasm branching table (`br_table`) operators. +pub trait WasmBrTable { + /// Returns the number of branching targets, not including the default label. + fn len(&self) -> usize; + + /// Returns `true` if the branch table doesn't have any labels apart from the default one. + fn is_empty(&self) -> bool; + + /// Returns the branch offset for the target at the given index. + fn target_offset(&self, at: usize) -> Option; + + /// Returns the default branch offset. + fn default_offset(&self) -> u32; +} + +/// Trait implemented by Wasm branching table builders. +/// +/// A branching table builder can build up a Wasm branch table incrementally +/// while upholding its invariants throughout the building process. This way +/// the internals of the Wasm branching table are less constraint by the build +/// procedure. +pub trait WasmBrTableBuilder: Default { + /// The branch table that is going to be build. + type BrTable; + + /// Pushes another branching target offset to the built branch table. + fn push_target(&mut self, offset: u32); + + /// Finalizes the branching table with the given default offset. + fn default_target(self, default_offset: u32) -> Self::BrTable; +} + /// A branch table (`br_table`). /// /// Stores its target and default branch offsets. #[derive(Debug, Clone)] pub struct BrTable2 { /// Non-empty vector storing the target offsets followed by the default offset. - targets: Vec, + targets: Box<[u32]>, + /// The default target offset. + default_target: u32, } -impl BrTable2 { - /// Creates a new branch table builder. - pub fn new() -> BrTableBuilder { - BrTableBuilder::default() - } - - /// Returns an iterator over the non-default branching targets. - pub fn non_default_targets<'a>(&'a self) -> impl Iterator + 'a { - self.targets.iter().copied() - } - - /// Returns an iterator over the branching targets. - pub fn targets(&self) -> core::slice::Iter { - self.targets.iter() +impl WasmBrTable for BrTable2 { + fn len(&self) -> usize { + self.targets.len().saturating_sub(1) } - /// Returns the number of non-default branch targets. - pub fn len_non_default_targets(&self) -> usize { - self.targets.len().saturating_sub(1) + fn is_empty(&self) -> bool { + self.len() == 0 } - /// Returns the number of branch target. - pub fn len_targets(&self) -> usize { - self.targets.len() + fn target_offset(&self, at: usize) -> Option { + self.targets.get(at).copied() } - /// Returns the default branch offset. - pub fn default_offset(&self) -> u32 { - self.targets.last().copied().expect("targets list is empty") + fn default_offset(&self) -> u32 { + self.default_target } } @@ -264,37 +284,30 @@ impl BrTable2 { #[derive(Debug)] pub struct BrTableBuilder { /// The building branch table. - br_table: BrTable2, + targets: Vec, } impl Default for BrTableBuilder { fn default() -> Self { - Self { br_table: BrTable2 { targets: Vec::new() } } + Self { + targets: Vec::new(), + } } } -impl BrTableBuilder { - /// Pushes another branching target to the branch table. - pub fn push_target(mut self, target: u32) -> Self { - self.br_table.targets.push(target); - self - } +impl WasmBrTableBuilder for BrTableBuilder { + type BrTable = BrTable2; - /// Pushes the given branching targets to the branch table. - pub fn push_targets(mut self, targets: I) -> Self - where - I: IntoIterator, - { - for target in targets { - self.br_table.targets.push(target); - } - self + fn push_target(&mut self, target: u32) { + self.targets.push(target); } - /// Finalizes the branch table with the given default branching offset. - pub fn default_target(mut self, default_target: u32) -> BrTable2 { - self.br_table.targets.push(default_target); - self.br_table + fn default_target(mut self, default_target: u32) -> BrTable2 { + self.targets.push(default_target); + BrTable2 { + targets: self.targets.into_boxed_slice(), + default_target, + } } } From 14466eb22c565b521f8918b8f8597c14d043b553 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 15:18:50 +0200 Subject: [PATCH 3/9] improve WasbBrTableBuilder trait --- src/primitives.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/primitives.rs b/src/primitives.rs index 54530ba7..c40831a0 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -240,10 +240,17 @@ pub trait WasmBrTable { /// while upholding its invariants throughout the building process. This way /// the internals of the Wasm branching table are less constraint by the build /// procedure. -pub trait WasmBrTableBuilder: Default { +pub trait WasmBrTableBuilder { /// The branch table that is going to be build. type BrTable; + /// Creates a new branch table builder. + /// + /// The `targets_hint` tells the builder how many branch targets it can + /// expect. This can be used by the builder in order to speed-up + /// the branch table construction. + fn new(targets_hint: usize) -> Self; + /// Pushes another branching target offset to the built branch table. fn push_target(&mut self, offset: u32); @@ -287,17 +294,13 @@ pub struct BrTableBuilder { targets: Vec, } -impl Default for BrTableBuilder { - fn default() -> Self { - Self { - targets: Vec::new(), - } - } -} - impl WasmBrTableBuilder for BrTableBuilder { type BrTable = BrTable2; + fn new(targets_hint: usize) -> Self { + Self { targets: Vec::with_capacity(targets_hint) } + } + fn push_target(&mut self, target: u32) { self.targets.push(target); } From d6cae854d508d63c615a6ab6990222ee8ca4c422 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 15:19:18 +0200 Subject: [PATCH 4/9] integrate the new BrTable type into the parser --- src/binary_reader.rs | 88 ++++++++++++++++++++++++++++---------- src/lib.rs | 2 + src/operators_validator.rs | 22 +++++++--- src/parser.rs | 4 +- src/primitives.rs | 4 +- src/readers/operators.rs | 10 ++--- src/validator.rs | 2 +- 7 files changed, 94 insertions(+), 38 deletions(-) diff --git a/src/binary_reader.rs b/src/binary_reader.rs index 96377fb3..de394b36 100644 --- a/src/binary_reader.rs +++ b/src/binary_reader.rs @@ -24,8 +24,8 @@ use crate::limits::{ }; use crate::primitives::{ - BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32, - Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, + BinaryReaderError, BrTable, BrTable2, CustomSectionKind, ExternalKind, FuncType, GlobalType, + Ieee32, Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, ResizableLimits, Result, SIMDLaneIndex, SectionCode, TableType, Type, TypeOrFuncType, V128, }; @@ -361,23 +361,8 @@ impl<'a> BinaryReader<'a> { } } - fn read_br_table(&mut self) -> Result> { - let targets_len = self.read_var_u32()? as usize; - if targets_len > MAX_WASM_BR_TABLE_SIZE { - return Err(BinaryReaderError::new( - "br_table size is out of bound", - self.original_position() - 1, - )); - } - let start = self.position; - for _ in 0..targets_len { - self.skip_var_32()?; - } - self.skip_var_32()?; - Ok(BrTable { - buffer: &self.buffer[start..self.position], - cnt: targets_len as usize, - }) + fn read_br_table(&mut self) -> Result { + BrTable2::read_table::(self.buffer) } /// Returns whether the `BinaryReader` has reached the end of the file. @@ -712,7 +697,7 @@ impl<'a> BinaryReader<'a> { Ok(imm) } - fn read_0xfe_operator(&mut self) -> Result> { + fn read_0xfe_operator(&mut self) -> Result { let code = self.read_u8()? as u8; Ok(match code { 0x00 => Operator::AtomicNotify { @@ -944,7 +929,7 @@ impl<'a> BinaryReader<'a> { /// # Errors /// If `BinaryReader` has less bytes remaining than required to parse /// the `Operator`. - pub fn read_operator(&mut self) -> Result> { + pub fn read_operator(&mut self) -> Result { let code = self.read_u8()? as u8; Ok(match code { 0x00 => Operator::Unreachable, @@ -1252,7 +1237,7 @@ impl<'a> BinaryReader<'a> { }) } - fn read_0xfc_operator(&mut self) -> Result> { + fn read_0xfc_operator(&mut self) -> Result { let code = self.read_u8()? as u8; Ok(match code { 0x00 => Operator::I32TruncSatF32S, @@ -1364,7 +1349,7 @@ impl<'a> BinaryReader<'a> { Ok(V128(bytes)) } - fn read_0xfd_operator(&mut self) -> Result> { + fn read_0xfd_operator(&mut self) -> Result { let code = self.read_var_u32()?; Ok(match code { 0x00 => Operator::V128Load { @@ -1696,6 +1681,63 @@ impl<'a> BinaryReader<'a> { } } +use crate::primitives::WasmBrTableBuilder; + +impl BrTable2 { + /// Reads branch table (`br_table`) entries from the given buffer. + /// + /// # Examples + /// + /// ```rust + /// // `0x0e` (`br_table` ID) and count already parsed at this point: + /// let buffer = vec![0x02, 0x01, 0x02, 0x00]; + /// # use wasmparser::{BrTable2, WasmBrTable, WasmBrTableBuilder}; + /// let br_table = BrTable2::read_table::(&buffer).unwrap(); + /// let expected = { + /// let mut builder = BrTableBuilder::default(); + /// builder.push_target(1); + /// builder.push_target(2); + /// builder.default_target(0) + /// }; + /// assert_eq!(br_table, expected); + /// ``` + pub fn read_table(buffer: &[u8]) -> Result + where + B: WasmBrTableBuilder, + { + let mut reader = BinaryReader::new(buffer); + let targets_len = reader.read_var_u32().map_err(|_| { + BinaryReaderError::new( + "br_table: missing target count", + reader.original_position(), + ) + })? as usize; + if targets_len > MAX_WASM_BR_TABLE_SIZE { + return Err(BinaryReaderError::new( + "br_table: size is out of bound", + reader.original_position() - 1, + )); + } + let mut builder = ::new(targets_len); + for _ in 0..targets_len { + let target = reader.read_var_u32().map_err(|_| { + BinaryReaderError::new( + "br_table: encountered invalid or missing branch target", + reader.original_position(), + ) + })?; + builder.push_target(target); + } + let default_target = reader.read_var_u32().map_err(|_| { + BinaryReaderError::new( + "br_table: missing default target", + reader.original_position(), + ) + })?; + Ok(builder.default_target(default_target)) + } +} + impl<'a> BrTable<'a> { /// Returns the number of `br_table` entries, not including the default /// label diff --git a/src/lib.rs b/src/lib.rs index 96fb359b..9b6fc8f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,8 @@ pub use crate::parser::WasmDecoder; pub use crate::primitives::BinaryReaderError; pub use crate::primitives::BrTable; pub use crate::primitives::BrTable2; +pub use crate::primitives::WasmBrTable; +pub use crate::primitives::WasmBrTableBuilder; pub use crate::primitives::BrTableBuilder; pub use crate::primitives::CustomSectionKind; pub use crate::primitives::ExternalKind; diff --git a/src/operators_validator.rs b/src/operators_validator.rs index f9ca198d..8b5339d7 100644 --- a/src/operators_validator.rs +++ b/src/operators_validator.rs @@ -947,14 +947,26 @@ impl OperatorValidator { Operator::BrTable { ref table } => { self.check_operands_1(Type::I32)?; let mut depth0: Option = None; - for relative_depth in table { + use crate::WasmBrTable as _; + let len_targets = table.len(); + fn check_target(validator: &OperatorValidator, depth0: &mut Option, relative_depth: u32) -> OperatorValidatorResult<()> { if depth0.is_none() { - self.check_jump_from_block(relative_depth, 1)?; - depth0 = Some(relative_depth); - continue; + validator.check_jump_from_block(relative_depth, 1)?; + depth0.replace(relative_depth); + } else { + validator.match_block_return(relative_depth, depth0.unwrap())?; } - self.match_block_return(relative_depth, depth0.unwrap())?; + validator.match_block_return(relative_depth, depth0.unwrap())?; + Ok(()) + } + // Check normal branch targets: + for i in 0..len_targets { + let relative_depth = table.target_offset(i).expect("encountered missing target"); + check_target(self, &mut depth0, relative_depth)?; } + // Check default branch target: + let default_depth = table.default_offset(); + check_target(self, &mut depth0, default_depth)?; self.func_state.start_dead_code() } Operator::Return => { diff --git a/src/parser.rs b/src/parser.rs index f8ef88d9..5f9b8646 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -104,7 +104,7 @@ pub enum ParserState<'a> { DataCountSectionEntry(u32), BeginInitExpressionBody, - InitExpressionOperator(Operator<'a>), + InitExpressionOperator(Operator), EndInitExpressionBody, BeginFunctionBody { @@ -113,7 +113,7 @@ pub enum ParserState<'a> { FunctionBodyLocals { locals: Box<[(u32, Type)]>, }, - CodeOperator(Operator<'a>), + CodeOperator(Operator), EndFunctionBody, SkippingFunctionBody, diff --git a/src/primitives.rs b/src/primitives.rs index c40831a0..d67b7f63 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -355,7 +355,7 @@ pub type SIMDLaneIndex = u8; /// /// [here]: https://webassembly.github.io/spec/core/binary/instructions.html #[derive(Debug, Clone)] -pub enum Operator<'a> { +pub enum Operator { Unreachable, Nop, Block { ty: TypeOrFuncType }, @@ -365,7 +365,7 @@ pub enum Operator<'a> { End, Br { relative_depth: u32 }, BrIf { relative_depth: u32 }, - BrTable { table: BrTable<'a> }, + BrTable { table: BrTable2 }, Return, Call { function_index: u32 }, CallIndirect { index: u32, table_index: u32 }, diff --git a/src/readers/operators.rs b/src/readers/operators.rs index 6791ab80..c0f1b27e 100644 --- a/src/readers/operators.rs +++ b/src/readers/operators.rs @@ -48,7 +48,7 @@ impl<'a> OperatorsReader<'a> { )) } - pub fn read<'b>(&mut self) -> Result> + pub fn read<'b>(&mut self) -> Result where 'a: 'b, { @@ -65,7 +65,7 @@ impl<'a> OperatorsReader<'a> { } } - pub fn read_with_offset<'b>(&mut self) -> Result<(Operator<'b>, usize)> + pub fn read_with_offset<'b>(&mut self) -> Result<(Operator, usize)> where 'a: 'b, { @@ -75,7 +75,7 @@ impl<'a> OperatorsReader<'a> { } impl<'a> IntoIterator for OperatorsReader<'a> { - type Item = Result>; + type Item = Result; type IntoIter = OperatorsIterator<'a>; /// Reads content of the code section. @@ -116,7 +116,7 @@ pub struct OperatorsIterator<'a> { } impl<'a> Iterator for OperatorsIterator<'a> { - type Item = Result>; + type Item = Result; fn next(&mut self) -> Option { if self.err || self.reader.eof() { @@ -134,7 +134,7 @@ pub struct OperatorsIteratorWithOffsets<'a> { } impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> { - type Item = Result<(Operator<'a>, usize)>; + type Item = Result<(Operator, usize)>; /// Reads content of the code section with offsets. /// diff --git a/src/validator.rs b/src/validator.rs index 6b2ec95b..e232d806 100644 --- a/src/validator.rs +++ b/src/validator.rs @@ -853,7 +853,7 @@ impl<'b> ValidatingOperatorParser<'b> { MemoryType = M, GlobalType = G, >, - ) -> Result> + ) -> Result where 'b: 'c, { From a739f4db04f03bae4ad8adb1731efcca6072f2be Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 16:08:16 +0200 Subject: [PATCH 5/9] fix BrTable2::read_table --- src/binary_reader.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/binary_reader.rs b/src/binary_reader.rs index de394b36..24ae99f2 100644 --- a/src/binary_reader.rs +++ b/src/binary_reader.rs @@ -362,7 +362,7 @@ impl<'a> BinaryReader<'a> { } fn read_br_table(&mut self) -> Result { - BrTable2::read_table::(self.buffer) + BrTable2::read_table::(self) } /// Returns whether the `BinaryReader` has reached the end of the file. @@ -1689,28 +1689,25 @@ impl BrTable2 { /// # Examples /// /// ```rust + /// # use wasmparser::{BinaryReader, BrTable2, BrTableBuilder, WasmBrTable, WasmBrTableBuilder}; /// // `0x0e` (`br_table` ID) and count already parsed at this point: /// let buffer = vec![0x02, 0x01, 0x02, 0x00]; - /// # use wasmparser::{BrTable2, WasmBrTable, WasmBrTableBuilder}; - /// let br_table = BrTable2::read_table::(&buffer).unwrap(); + /// let mut reader = BinaryReader::new(&buffer); + /// let br_table = BrTable2::read_table::(&mut reader).unwrap(); /// let expected = { - /// let mut builder = BrTableBuilder::default(); + /// let mut builder = BrTableBuilder::new(2); /// builder.push_target(1); /// builder.push_target(2); /// builder.default_target(0) /// }; /// assert_eq!(br_table, expected); /// ``` - pub fn read_table(buffer: &[u8]) -> Result + pub fn read_table(reader: &mut BinaryReader) -> Result where B: WasmBrTableBuilder, { - let mut reader = BinaryReader::new(buffer); let targets_len = reader.read_var_u32().map_err(|_| { - BinaryReaderError::new( - "br_table: missing target count", - reader.original_position(), - ) + BinaryReaderError::new("br_table: missing target count", reader.original_position()) })? as usize; if targets_len > MAX_WASM_BR_TABLE_SIZE { return Err(BinaryReaderError::new( From 3b1ba699a07b16c0b77ef40e4af23f12e78f2097 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 16:08:39 +0200 Subject: [PATCH 6/9] add PartialEq and Eq derives for BrTable2 --- src/primitives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/primitives.rs b/src/primitives.rs index d67b7f63..a4df9b3e 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -261,7 +261,7 @@ pub trait WasmBrTableBuilder { /// A branch table (`br_table`). /// /// Stores its target and default branch offsets. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct BrTable2 { /// Non-empty vector storing the target offsets followed by the default offset. targets: Box<[u32]>, From fcc0bb9cb67f2b8737a3b29a72231a1cba2dbe7e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 16:09:51 +0200 Subject: [PATCH 7/9] remove old BrTable struct and impls --- src/binary_reader.rs | 86 +------------------------------------------- src/lib.rs | 1 - src/primitives.rs | 7 ---- 3 files changed, 1 insertion(+), 93 deletions(-) diff --git a/src/binary_reader.rs b/src/binary_reader.rs index 24ae99f2..3a674c7c 100644 --- a/src/binary_reader.rs +++ b/src/binary_reader.rs @@ -13,7 +13,6 @@ * limitations under the License. */ -use std::boxed::Box; use std::convert::TryInto; use std::str; use std::vec::Vec; @@ -24,7 +23,7 @@ use crate::limits::{ }; use crate::primitives::{ - BinaryReaderError, BrTable, BrTable2, CustomSectionKind, ExternalKind, FuncType, GlobalType, + BinaryReaderError, BrTable2, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32, Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, ResizableLimits, Result, SIMDLaneIndex, SectionCode, TableType, Type, TypeOrFuncType, V128, }; @@ -1734,86 +1733,3 @@ impl BrTable2 { Ok(builder.default_target(default_target)) } } - -impl<'a> BrTable<'a> { - /// Returns the number of `br_table` entries, not including the default - /// label - pub fn len(&self) -> usize { - self.cnt - } - - /// Returns whether `BrTable` doesn't have any labels apart from the default one. - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Reads br_table entries. - /// - /// # Examples - /// ```rust - /// let buf = vec![0x0e, 0x02, 0x01, 0x02, 0x00]; - /// let mut reader = wasmparser::BinaryReader::new(&buf); - /// let op = reader.read_operator().unwrap(); - /// if let wasmparser::Operator::BrTable { ref table } = op { - /// let br_table_depths = table.read_table().unwrap(); - /// assert!(br_table_depths.0 == vec![1,2].into_boxed_slice() && - /// br_table_depths.1 == 0); - /// } else { - /// unreachable!(); - /// } - /// ``` - pub fn read_table(&self) -> Result<(Box<[u32]>, u32)> { - let mut reader = BinaryReader::new(self.buffer); - let mut table = Vec::new(); - while !reader.eof() { - table.push(reader.read_var_u32()?); - } - let default_target = table.pop().ok_or_else(|| { - BinaryReaderError::new( - "br_table missing default target", - reader.original_position(), - ) - })?; - Ok((table.into_boxed_slice(), default_target)) - } -} - -/// Iterator for `BrTable`. -/// -/// #Examples -/// ```rust -/// let buf = vec![0x0e, 0x02, 0x01, 0x02, 0x00]; -/// let mut reader = wasmparser::BinaryReader::new(&buf); -/// let op = reader.read_operator().unwrap(); -/// if let wasmparser::Operator::BrTable { ref table } = op { -/// for depth in table { -/// println!("BrTable depth: {}", depth); -/// } -/// } -/// ``` -#[derive(Clone, Debug)] -pub struct BrTableIterator<'a> { - reader: BinaryReader<'a>, -} - -impl<'a> IntoIterator for &'a BrTable<'a> { - type Item = u32; - type IntoIter = BrTableIterator<'a>; - - fn into_iter(self) -> Self::IntoIter { - BrTableIterator { - reader: BinaryReader::new(self.buffer), - } - } -} - -impl<'a> Iterator for BrTableIterator<'a> { - type Item = u32; - - fn next(&mut self) -> Option { - if self.reader.eof() { - return None; - } - self.reader.read_var_u32().ok() - } -} diff --git a/src/lib.rs b/src/lib.rs index 9b6fc8f5..67c9dc6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ pub use crate::parser::RelocEntry; pub use crate::parser::WasmDecoder; pub use crate::primitives::BinaryReaderError; -pub use crate::primitives::BrTable; pub use crate::primitives::BrTable2; pub use crate::primitives::WasmBrTable; pub use crate::primitives::WasmBrTableBuilder; diff --git a/src/primitives.rs b/src/primitives.rs index a4df9b3e..dee3324f 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -212,13 +212,6 @@ pub enum RelocType { GlobalIndexLEB, } -/// A br_table entries representation. -#[derive(Debug, Clone)] -pub struct BrTable<'a> { - pub(crate) buffer: &'a [u8], - pub(crate) cnt: usize, -} - /// Trait implemented by Wasm branching table (`br_table`) operators. pub trait WasmBrTable { /// Returns the number of branching targets, not including the default label. From db39955db86be097a76918ba31437160f03a0814 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 16:11:11 +0200 Subject: [PATCH 8/9] rename BrTable2 -> BrTable --- src/binary_reader.rs | 12 ++++++------ src/lib.rs | 2 +- src/primitives.rs | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/binary_reader.rs b/src/binary_reader.rs index 3a674c7c..ad75c09f 100644 --- a/src/binary_reader.rs +++ b/src/binary_reader.rs @@ -23,7 +23,7 @@ use crate::limits::{ }; use crate::primitives::{ - BinaryReaderError, BrTable2, CustomSectionKind, ExternalKind, FuncType, GlobalType, + BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32, Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, ResizableLimits, Result, SIMDLaneIndex, SectionCode, TableType, Type, TypeOrFuncType, V128, }; @@ -360,8 +360,8 @@ impl<'a> BinaryReader<'a> { } } - fn read_br_table(&mut self) -> Result { - BrTable2::read_table::(self) + fn read_br_table(&mut self) -> Result { + BrTable::read_table::(self) } /// Returns whether the `BinaryReader` has reached the end of the file. @@ -1682,17 +1682,17 @@ impl<'a> BinaryReader<'a> { use crate::primitives::WasmBrTableBuilder; -impl BrTable2 { +impl BrTable { /// Reads branch table (`br_table`) entries from the given buffer. /// /// # Examples /// /// ```rust - /// # use wasmparser::{BinaryReader, BrTable2, BrTableBuilder, WasmBrTable, WasmBrTableBuilder}; + /// # use wasmparser::{BinaryReader, BrTable, BrTableBuilder, WasmBrTable, WasmBrTableBuilder}; /// // `0x0e` (`br_table` ID) and count already parsed at this point: /// let buffer = vec![0x02, 0x01, 0x02, 0x00]; /// let mut reader = BinaryReader::new(&buffer); - /// let br_table = BrTable2::read_table::(&mut reader).unwrap(); + /// let br_table = BrTable::read_table::(&mut reader).unwrap(); /// let expected = { /// let mut builder = BrTableBuilder::new(2); /// builder.push_target(1); diff --git a/src/lib.rs b/src/lib.rs index 67c9dc6f..f07bf351 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,7 @@ pub use crate::parser::RelocEntry; pub use crate::parser::WasmDecoder; pub use crate::primitives::BinaryReaderError; -pub use crate::primitives::BrTable2; +pub use crate::primitives::BrTable; pub use crate::primitives::WasmBrTable; pub use crate::primitives::WasmBrTableBuilder; pub use crate::primitives::BrTableBuilder; diff --git a/src/primitives.rs b/src/primitives.rs index dee3324f..583c27a8 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -255,14 +255,14 @@ pub trait WasmBrTableBuilder { /// /// Stores its target and default branch offsets. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct BrTable2 { +pub struct BrTable { /// Non-empty vector storing the target offsets followed by the default offset. targets: Box<[u32]>, /// The default target offset. default_target: u32, } -impl WasmBrTable for BrTable2 { +impl WasmBrTable for BrTable { fn len(&self) -> usize { self.targets.len().saturating_sub(1) } @@ -288,7 +288,7 @@ pub struct BrTableBuilder { } impl WasmBrTableBuilder for BrTableBuilder { - type BrTable = BrTable2; + type BrTable = BrTable; fn new(targets_hint: usize) -> Self { Self { targets: Vec::with_capacity(targets_hint) } @@ -298,9 +298,9 @@ impl WasmBrTableBuilder for BrTableBuilder { self.targets.push(target); } - fn default_target(mut self, default_target: u32) -> BrTable2 { + fn default_target(mut self, default_target: u32) -> BrTable { self.targets.push(default_target); - BrTable2 { + BrTable { targets: self.targets.into_boxed_slice(), default_target, } @@ -358,7 +358,7 @@ pub enum Operator { End, Br { relative_depth: u32 }, BrIf { relative_depth: u32 }, - BrTable { table: BrTable2 }, + BrTable { table: BrTable }, Return, Call { function_index: u32 }, CallIndirect { index: u32, table_index: u32 }, From a99b159235138f815130a70139ed59b758e79987 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 17 May 2020 16:23:56 +0200 Subject: [PATCH 9/9] apply rustfmt --- src/binary_reader.rs | 4 ++-- src/lib.rs | 4 ++-- src/operators_validator.rs | 9 +++++++-- src/primitives.rs | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/binary_reader.rs b/src/binary_reader.rs index ad75c09f..0df1e6a2 100644 --- a/src/binary_reader.rs +++ b/src/binary_reader.rs @@ -23,8 +23,8 @@ use crate::limits::{ }; use crate::primitives::{ - BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, - Ieee32, Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, + BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32, + Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType, ResizableLimits, Result, SIMDLaneIndex, SectionCode, TableType, Type, TypeOrFuncType, V128, }; diff --git a/src/lib.rs b/src/lib.rs index f07bf351..8f8028bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,8 +38,6 @@ pub use crate::parser::WasmDecoder; pub use crate::primitives::BinaryReaderError; pub use crate::primitives::BrTable; -pub use crate::primitives::WasmBrTable; -pub use crate::primitives::WasmBrTableBuilder; pub use crate::primitives::BrTableBuilder; pub use crate::primitives::CustomSectionKind; pub use crate::primitives::ExternalKind; @@ -61,6 +59,8 @@ pub use crate::primitives::SectionCode; pub use crate::primitives::TableType; pub use crate::primitives::Type; pub use crate::primitives::TypeOrFuncType; +pub use crate::primitives::WasmBrTable; +pub use crate::primitives::WasmBrTableBuilder; pub use crate::primitives::V128; pub use crate::validator::validate; diff --git a/src/operators_validator.rs b/src/operators_validator.rs index 8b5339d7..f7662d49 100644 --- a/src/operators_validator.rs +++ b/src/operators_validator.rs @@ -949,7 +949,11 @@ impl OperatorValidator { let mut depth0: Option = None; use crate::WasmBrTable as _; let len_targets = table.len(); - fn check_target(validator: &OperatorValidator, depth0: &mut Option, relative_depth: u32) -> OperatorValidatorResult<()> { + fn check_target( + validator: &OperatorValidator, + depth0: &mut Option, + relative_depth: u32, + ) -> OperatorValidatorResult<()> { if depth0.is_none() { validator.check_jump_from_block(relative_depth, 1)?; depth0.replace(relative_depth); @@ -961,7 +965,8 @@ impl OperatorValidator { } // Check normal branch targets: for i in 0..len_targets { - let relative_depth = table.target_offset(i).expect("encountered missing target"); + let relative_depth = + table.target_offset(i).expect("encountered missing target"); check_target(self, &mut depth0, relative_depth)?; } // Check default branch target: diff --git a/src/primitives.rs b/src/primitives.rs index 583c27a8..5e546b88 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -291,7 +291,9 @@ impl WasmBrTableBuilder for BrTableBuilder { type BrTable = BrTable; fn new(targets_hint: usize) -> Self { - Self { targets: Vec::with_capacity(targets_hint) } + Self { + targets: Vec::with_capacity(targets_hint), + } } fn push_target(&mut self, target: u32) {