Skip to content

Commit 17022cf

Browse files
authored
Fix passive element reader (bytecodealliance#150)
1 parent 3be1da9 commit 17022cf

6 files changed

Lines changed: 106 additions & 31 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "wasmparser"
3-
version = "0.42.1"
3+
version = "0.43.0"
44
authors = ["Yury Delendik <ydelendik@mozilla.com>"]
55
license = "Apache-2.0 WITH LLVM-exception"
66
repository = "https://github.com/yurydelendik/wasmparser.rs"

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub use crate::readers::NamingReader;
111111
pub use crate::readers::OperatorsReader;
112112
pub use crate::readers::PassiveElementItem;
113113
pub use crate::readers::PassiveElementItems;
114+
pub use crate::readers::PassiveElementItemsReader;
114115
pub use crate::readers::ProducersField;
115116
pub use crate::readers::ProducersFieldValue;
116117
pub use crate::readers::ProducersSectionReader;

src/parser.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ use crate::readers::{
3131
ActiveElementItems, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementKind,
3232
ElementSectionReader, Export, ExportSectionReader, FunctionBody, FunctionSectionReader, Global,
3333
GlobalSectionReader, Import, ImportSectionReader, LinkingSectionReader, MemorySectionReader,
34-
ModuleReader, Name, NameSectionReader, NamingReader, OperatorsReader, PassiveElementItems,
35-
Reloc, RelocSectionReader, Section, SectionReader, TableSectionReader, TypeSectionReader,
34+
ModuleReader, Name, NameSectionReader, NamingReader, OperatorsReader, PassiveElementItem,
35+
PassiveElementItems, Reloc, RelocSectionReader, Section, SectionReader, TableSectionReader,
36+
TypeSectionReader,
3637
};
3738

3839
use crate::binary_reader::{BinaryReader, Range};
@@ -116,9 +117,12 @@ pub enum ParserState<'a> {
116117
EndFunctionBody,
117118
SkippingFunctionBody,
118119

119-
BeginPassiveElementSectionEntry(Type),
120120
BeginActiveElementSectionEntry(u32),
121121
ElementSectionEntryBody(Box<[u32]>),
122+
PassiveElementSectionEntry {
123+
ty: Type,
124+
items: Box<[PassiveElementItem]>,
125+
},
122126
EndElementSectionEntry,
123127

124128
BeginPassiveDataSectionEntry,
@@ -204,7 +208,6 @@ pub struct Parser<'a> {
204208
module_reader: Option<ModuleReader<'a>>,
205209
current_section: Option<Section<'a>>,
206210
section_reader: ParserSectionReader<'a>,
207-
passive_element_items: Option<PassiveElementItems<'a>>,
208211
active_element_items: Option<ActiveElementItems<'a>>,
209212
current_function_body: Option<FunctionBody<'a>>,
210213
init_expr_continuation: Option<InitExpressionContinuationSection>,
@@ -232,7 +235,6 @@ impl<'a> Parser<'a> {
232235
current_section: None,
233236
section_reader: ParserSectionReader::None,
234237
active_element_items: None,
235-
passive_element_items: None,
236238
current_function_body: None,
237239
init_expr_continuation: None,
238240
current_data_segment: None,
@@ -424,8 +426,10 @@ impl<'a> Parser<'a> {
424426
let Element { kind } = section_reader!(self, ElementSectionReader).read()?;
425427
match kind {
426428
ElementKind::Passive { ty, items } => {
427-
self.state = ParserState::BeginPassiveElementSectionEntry(ty);
428-
self.passive_element_items = Some(items);
429+
self.state = ParserState::PassiveElementSectionEntry {
430+
ty,
431+
items: self.read_passive_elements(items)?,
432+
};
429433
}
430434
ElementKind::Active {
431435
table_index,
@@ -462,6 +466,22 @@ impl<'a> Parser<'a> {
462466
Ok(())
463467
}
464468

469+
fn read_passive_elements(
470+
&mut self,
471+
items: PassiveElementItems,
472+
) -> Result<Box<[PassiveElementItem]>> {
473+
let reader = items.get_items_reader()?;
474+
let num_elements = reader.get_count() as usize;
475+
if num_elements > MAX_WASM_TABLE_ENTRIES {
476+
return Err(BinaryReaderError {
477+
message: "num_elements is out of bounds",
478+
offset: 0, // reader.position - 1, // TODO offset
479+
});
480+
}
481+
let elements: Vec<PassiveElementItem> = reader.into_iter().collect::<Result<Vec<_>>>()?;
482+
Ok(elements.into_boxed_slice())
483+
}
484+
465485
fn read_function_body(&mut self) -> Result<()> {
466486
if self.section_entries_left == 0 {
467487
self.current_function_body = None;
@@ -914,7 +934,7 @@ impl<'a> Parser<'a> {
914934
self.read_init_expression_body(InitExpressionContinuationSection::Global)
915935
}
916936
ParserState::EndGlobalSectionEntry => self.read_global_entry()?,
917-
ParserState::BeginPassiveElementSectionEntry(_) => self.read_element_entry_body()?,
937+
ParserState::PassiveElementSectionEntry { .. } => self.read_element_entry()?,
918938
ParserState::BeginActiveElementSectionEntry(_) => {
919939
self.read_init_expression_body(InitExpressionContinuationSection::Element)
920940
}

src/readers/element_section.rs

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,40 @@ impl<'a> Iterator for ActiveElementItemsIterator<'a> {
115115

116116
#[derive(Clone)]
117117
pub struct PassiveElementItems<'a> {
118+
offset: usize,
119+
data: &'a [u8],
118120
amt: u32,
119-
reader: OperatorsReader<'a>,
120121
}
121122

123+
impl<'a> PassiveElementItems<'a> {
124+
pub fn get_items_reader<'b>(&self) -> Result<PassiveElementItemsReader<'b>>
125+
where
126+
'a: 'b,
127+
{
128+
PassiveElementItemsReader::new(self.data, self.offset, self.amt)
129+
}
130+
}
131+
132+
#[derive(Debug, Clone)]
122133
pub enum PassiveElementItem {
123134
Null,
124135
Func(u32),
125136
}
126137

127-
impl<'a> PassiveElementItems<'a> {
138+
#[derive(Clone)]
139+
pub struct PassiveElementItemsReader<'a> {
140+
reader: OperatorsReader<'a>,
141+
count: u32,
142+
}
143+
144+
impl<'a> PassiveElementItemsReader<'a> {
145+
pub fn new(data: &[u8], offset: usize, count: u32) -> Result<PassiveElementItemsReader> {
146+
let reader = OperatorsReader::new(data, offset);
147+
Ok(PassiveElementItemsReader { reader, count })
148+
}
149+
128150
pub fn get_count(&self) -> u32 {
129-
self.amt
151+
self.count
130152
}
131153

132154
pub fn read(&mut self) -> Result<PassiveElementItem> {
@@ -149,14 +171,46 @@ impl<'a> PassiveElementItems<'a> {
149171
})
150172
}
151173
}
152-
self.amt -= 1;
153-
if self.amt == 0 {
154-
self.reader.ensure_end()?;
155-
}
156174
Ok(ret)
157175
}
158176
}
159177

178+
impl<'a> IntoIterator for PassiveElementItemsReader<'a> {
179+
type Item = Result<PassiveElementItem>;
180+
type IntoIter = PassiveElementItemsIterator<'a>;
181+
fn into_iter(self) -> Self::IntoIter {
182+
let count = self.count;
183+
PassiveElementItemsIterator {
184+
reader: self,
185+
left: count,
186+
err: false,
187+
}
188+
}
189+
}
190+
191+
pub struct PassiveElementItemsIterator<'a> {
192+
reader: PassiveElementItemsReader<'a>,
193+
left: u32,
194+
err: bool,
195+
}
196+
197+
impl<'a> Iterator for PassiveElementItemsIterator<'a> {
198+
type Item = Result<PassiveElementItem>;
199+
fn next(&mut self) -> Option<Self::Item> {
200+
if self.err || self.left == 0 {
201+
return None;
202+
}
203+
let result = self.reader.read();
204+
self.err = result.is_err();
205+
self.left -= 1;
206+
Some(result)
207+
}
208+
fn size_hint(&self) -> (usize, Option<usize>) {
209+
let count = self.reader.get_count() as usize;
210+
(count, Some(count))
211+
}
212+
}
213+
160214
pub struct ElementSectionReader<'a> {
161215
reader: BinaryReader<'a>,
162216
count: u32,
@@ -184,7 +238,8 @@ impl<'a> ElementSectionReader<'a> {
184238
/// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
185239
/// # 0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
186240
/// # 0x05, 0x03, 0x01, 0x00, 0x02,
187-
/// # 0x09, 0x07, 0x01, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
241+
/// # 0x09, 0x0F, 0x02, 0x00, 0x41, 0x00, 0x0B, 0x01, 0x00,
242+
/// # 0x01, 0x70, 0x02, 0xD0, 0x0B, 0xD2, 0x00, 0x0B,
188243
/// # 0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
189244
/// use wasmparser::{ModuleReader, ElementKind};
190245
///use wasmparser::Result;
@@ -206,6 +261,14 @@ impl<'a> ElementSectionReader<'a> {
206261
/// println!(" Item: {}", item);
207262
/// }
208263
/// }
264+
/// if let ElementKind::Passive { ty, items } = element.kind {
265+
/// println!("Type: {:?}", ty);
266+
/// let mut items_reader = items.get_items_reader().expect("items reader");
267+
/// for _ in 0..items_reader.get_count() {
268+
/// let item = items_reader.read().expect("item");
269+
/// println!(" Item: {:?}", item);
270+
/// }
271+
/// }
209272
/// }
210273
/// ```
211274
pub fn read<'b>(&mut self) -> Result<Element<'b>>
@@ -217,24 +280,14 @@ impl<'a> ElementSectionReader<'a> {
217280
let ty = self.reader.read_type()?;
218281
let amt = self.reader.read_var_u32()?;
219282
let data_start = self.reader.position;
220-
let mut reader = OperatorsReader {
221-
reader: self.reader.clone(),
222-
};
223283
for _ in 0..amt {
224-
loop {
225-
if let Operator::End = reader.read()? {
226-
break;
227-
}
228-
}
284+
self.reader.skip_init_expr()?;
229285
}
230-
self.reader = reader.reader;
231286
let data_end = self.reader.position;
232287
let items = PassiveElementItems {
233288
amt,
234-
reader: OperatorsReader::new(
235-
&self.reader.buffer[data_start..data_end],
236-
self.reader.original_offset + data_start,
237-
),
289+
offset: self.reader.original_offset + data_start,
290+
data: &self.reader.buffer[data_start..data_end],
238291
};
239292
ElementKind::Passive { ty, items }
240293
} else {

src/readers/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub use self::element_section::ElementKind;
3535
pub use self::element_section::ElementSectionReader;
3636
pub use self::element_section::PassiveElementItem;
3737
pub use self::element_section::PassiveElementItems;
38+
pub use self::element_section::PassiveElementItemsReader;
3839
pub use self::export_section::Export;
3940
pub use self::export_section::ExportSectionReader;
4041
pub use self::function_section::FunctionSectionReader;

src/validator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ impl<'a> ValidatingParser<'a> {
523523
ParserState::DataCountSectionEntry(count) => {
524524
self.resources.data_count = Some(count);
525525
}
526-
ParserState::BeginPassiveElementSectionEntry(_ty) => {
526+
ParserState::PassiveElementSectionEntry { .. } => {
527527
self.resources.element_count += 1;
528528
}
529529
ParserState::BeginActiveElementSectionEntry(table_index) => {

0 commit comments

Comments
 (0)