1 /* Copyright 2018 Mozilla Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 use super::{
17     BinaryReader, BinaryReaderError, InitExpr, Result, SectionIteratorLimited, SectionReader,
18     SectionWithLimitedItems, Type,
19 };
20 use crate::{ExternalKind, Operator};
21 
22 #[derive(Clone)]
23 pub struct Element<'a> {
24     pub kind: ElementKind<'a>,
25     pub items: ElementItems<'a>,
26     pub ty: Type,
27 }
28 
29 #[derive(Clone)]
30 pub enum ElementKind<'a> {
31     Passive,
32     Active {
33         table_index: u32,
34         init_expr: InitExpr<'a>,
35     },
36     Declared,
37 }
38 
39 #[derive(Debug, Copy, Clone)]
40 pub struct ElementItems<'a> {
41     exprs: bool,
42     offset: usize,
43     data: &'a [u8],
44 }
45 
46 #[derive(Debug)]
47 pub enum ElementItem {
48     Null(Type),
49     Func(u32),
50 }
51 
52 impl<'a> ElementItems<'a> {
get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>> where 'a: 'b,53     pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>>
54     where
55         'a: 'b,
56     {
57         ElementItemsReader::new(self.data, self.offset, self.exprs)
58     }
59 }
60 
61 pub struct ElementItemsReader<'a> {
62     reader: BinaryReader<'a>,
63     count: u32,
64     exprs: bool,
65 }
66 
67 impl<'a> ElementItemsReader<'a> {
new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader>68     pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> {
69         let mut reader = BinaryReader::new_with_offset(data, offset);
70         let count = reader.read_var_u32()?;
71         Ok(ElementItemsReader {
72             reader,
73             count,
74             exprs,
75         })
76     }
77 
original_position(&self) -> usize78     pub fn original_position(&self) -> usize {
79         self.reader.original_position()
80     }
81 
get_count(&self) -> u3282     pub fn get_count(&self) -> u32 {
83         self.count
84     }
85 
uses_exprs(&self) -> bool86     pub fn uses_exprs(&self) -> bool {
87         self.exprs
88     }
89 
read(&mut self) -> Result<ElementItem>90     pub fn read(&mut self) -> Result<ElementItem> {
91         if self.exprs {
92             let offset = self.reader.original_position();
93             let ret = match self.reader.read_operator()? {
94                 Operator::RefNull { ty } => ElementItem::Null(ty),
95                 Operator::RefFunc { function_index } => ElementItem::Func(function_index),
96                 _ => return Err(BinaryReaderError::new("invalid passive segment", offset)),
97             };
98             match self.reader.read_operator()? {
99                 Operator::End => {}
100                 _ => return Err(BinaryReaderError::new("invalid passive segment", offset)),
101             }
102             Ok(ret)
103         } else {
104             self.reader.read_var_u32().map(ElementItem::Func)
105         }
106     }
107 }
108 
109 impl<'a> IntoIterator for ElementItemsReader<'a> {
110     type Item = Result<ElementItem>;
111     type IntoIter = ElementItemsIterator<'a>;
into_iter(self) -> Self::IntoIter112     fn into_iter(self) -> Self::IntoIter {
113         let count = self.count;
114         ElementItemsIterator {
115             reader: self,
116             left: count,
117             err: false,
118         }
119     }
120 }
121 
122 pub struct ElementItemsIterator<'a> {
123     reader: ElementItemsReader<'a>,
124     left: u32,
125     err: bool,
126 }
127 
128 impl<'a> Iterator for ElementItemsIterator<'a> {
129     type Item = Result<ElementItem>;
next(&mut self) -> Option<Self::Item>130     fn next(&mut self) -> Option<Self::Item> {
131         if self.err || self.left == 0 {
132             return None;
133         }
134         let result = self.reader.read();
135         self.err = result.is_err();
136         self.left -= 1;
137         Some(result)
138     }
size_hint(&self) -> (usize, Option<usize>)139     fn size_hint(&self) -> (usize, Option<usize>) {
140         let count = self.reader.get_count() as usize;
141         (count, Some(count))
142     }
143 }
144 
145 pub struct ElementSectionReader<'a> {
146     reader: BinaryReader<'a>,
147     count: u32,
148 }
149 
150 impl<'a> ElementSectionReader<'a> {
new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>>151     pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> {
152         let mut reader = BinaryReader::new_with_offset(data, offset);
153         let count = reader.read_var_u32()?;
154         Ok(ElementSectionReader { reader, count })
155     }
156 
original_position(&self) -> usize157     pub fn original_position(&self) -> usize {
158         self.reader.original_position()
159     }
160 
get_count(&self) -> u32161     pub fn get_count(&self) -> u32 {
162         self.count
163     }
164 
165     /// Reads content of the element section.
166     ///
167     /// # Examples
168     ///
169     /// ```no_run
170     /// # let data: &[u8] = &[];
171     /// use wasmparser::{ModuleReader, ElementKind};
172     /// use wasmparser::Result;
173     /// let mut reader = ModuleReader::new(data).expect("module reader");
174     /// let section = reader.read().expect("type section");
175     /// let section = reader.read().expect("function section");
176     /// let section = reader.read().expect("table section");
177     /// let section = reader.read().expect("element section");
178     /// let mut element_reader = section.get_element_section_reader().expect("element section reader");
179     /// for _ in 0..element_reader.get_count() {
180     ///     let element = element_reader.read().expect("element");
181     ///     if let ElementKind::Active { init_expr, .. } = element.kind {
182     ///         let mut init_expr_reader = init_expr.get_binary_reader();
183     ///         let op = init_expr_reader.read_operator().expect("op");
184     ///         println!("Init const: {:?}", op);
185     ///     }
186     ///     let mut items_reader = element.items.get_items_reader().expect("items reader");
187     ///     for _ in 0..items_reader.get_count() {
188     ///         let item = items_reader.read().expect("item");
189     ///         println!("  Item: {:?}", item);
190     ///     }
191     /// }
192     /// ```
read<'b>(&mut self) -> Result<Element<'b>> where 'a: 'b,193     pub fn read<'b>(&mut self) -> Result<Element<'b>>
194     where
195         'a: 'b,
196     {
197         let flags = self.reader.read_var_u32()?;
198         if (flags & !0b111) != 0 {
199             return Err(BinaryReaderError::new(
200                 "invalid flags byte in element segment",
201                 self.reader.original_position() - 1,
202             ));
203         }
204         let kind = if flags & 0b001 != 0 {
205             if flags & 0b010 != 0 {
206                 ElementKind::Declared
207             } else {
208                 ElementKind::Passive
209             }
210         } else {
211             let table_index = if flags & 0b010 == 0 {
212                 0
213             } else {
214                 self.reader.read_var_u32()?
215             };
216             let init_expr = {
217                 let expr_offset = self.reader.position;
218                 self.reader.skip_init_expr()?;
219                 let data = &self.reader.buffer[expr_offset..self.reader.position];
220                 InitExpr::new(data, self.reader.original_offset + expr_offset)
221             };
222             ElementKind::Active {
223                 table_index,
224                 init_expr,
225             }
226         };
227         let exprs = flags & 0b100 != 0;
228         let ty = if flags & 0b011 != 0 {
229             if exprs {
230                 self.reader.read_type()?
231             } else {
232                 match self.reader.read_external_kind()? {
233                     ExternalKind::Function => Type::FuncRef,
234                     _ => {
235                         return Err(BinaryReaderError::new(
236                             "only the function external type is supported in elem segment",
237                             self.reader.original_position() - 1,
238                         ));
239                     }
240                 }
241             }
242         } else {
243             Type::FuncRef
244         };
245         let data_start = self.reader.position;
246         let items_count = self.reader.read_var_u32()?;
247         if exprs {
248             for _ in 0..items_count {
249                 self.reader.skip_init_expr()?;
250             }
251         } else {
252             for _ in 0..items_count {
253                 self.reader.skip_var_32()?;
254             }
255         }
256         let data_end = self.reader.position;
257         let items = ElementItems {
258             offset: self.reader.original_offset + data_start,
259             data: &self.reader.buffer[data_start..data_end],
260             exprs,
261         };
262         Ok(Element { kind, items, ty })
263     }
264 }
265 
266 impl<'a> SectionReader for ElementSectionReader<'a> {
267     type Item = Element<'a>;
read(&mut self) -> Result<Self::Item>268     fn read(&mut self) -> Result<Self::Item> {
269         ElementSectionReader::read(self)
270     }
eof(&self) -> bool271     fn eof(&self) -> bool {
272         self.reader.eof()
273     }
original_position(&self) -> usize274     fn original_position(&self) -> usize {
275         ElementSectionReader::original_position(self)
276     }
277 }
278 
279 impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> {
get_count(&self) -> u32280     fn get_count(&self) -> u32 {
281         ElementSectionReader::get_count(self)
282     }
283 }
284 
285 impl<'a> IntoIterator for ElementSectionReader<'a> {
286     type Item = Result<Element<'a>>;
287     type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>;
288 
into_iter(self) -> Self::IntoIter289     fn into_iter(self) -> Self::IntoIter {
290         SectionIteratorLimited::new(self)
291     }
292 }
293