/src/wasm-tools/crates/wasmparser/src/readers/element_section.rs
Line | Count | Source (jump to first uncovered line) |
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, Range, Result, SectionIteratorLimited, |
18 | | SectionReader, SectionWithLimitedItems, Type, |
19 | | }; |
20 | | use crate::{ExternalKind, Operator}; |
21 | | |
22 | 0 | #[derive(Clone)] |
23 | | pub struct Element<'a> { |
24 | | pub kind: ElementKind<'a>, |
25 | | pub items: ElementItems<'a>, |
26 | | pub ty: Type, |
27 | | } |
28 | | |
29 | 0 | #[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 | 0 | #[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> { |
53 | 860k | pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>> |
54 | 860k | where |
55 | 860k | 'a: 'b, |
56 | 860k | { |
57 | 860k | ElementItemsReader::new(self.data, self.offset, self.exprs) |
58 | 860k | } |
59 | | } |
60 | | |
61 | | pub struct ElementItemsReader<'a> { |
62 | | reader: BinaryReader<'a>, |
63 | | count: u32, |
64 | | exprs: bool, |
65 | | } |
66 | | |
67 | | impl<'a> ElementItemsReader<'a> { |
68 | 860k | pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> { |
69 | 860k | let mut reader = BinaryReader::new_with_offset(data, offset); |
70 | 860k | let count = reader.read_var_u32()?; |
71 | 860k | Ok(ElementItemsReader { |
72 | 860k | reader, |
73 | 860k | count, |
74 | 860k | exprs, |
75 | 860k | }) |
76 | 860k | } |
77 | | |
78 | 36.7M | pub fn original_position(&self) -> usize { |
79 | 36.7M | self.reader.original_position() |
80 | 36.7M | } |
81 | | |
82 | 1.60M | pub fn get_count(&self) -> u32 { |
83 | 1.60M | self.count |
84 | 1.60M | } |
85 | | |
86 | 2.02M | pub fn uses_exprs(&self) -> bool { |
87 | 2.02M | self.exprs |
88 | 2.02M | } |
89 | | |
90 | 38.6M | pub fn read(&mut self) -> Result<ElementItem> { |
91 | 38.6M | if self.exprs { |
92 | 35.2M | let offset = self.reader.original_position(); |
93 | 35.2M | let ret = match self.reader.read_operator()? { |
94 | 35.2M | Operator::RefNull { ty } => ElementItem::Null(ty), |
95 | 41.0k | Operator::RefFunc { function_index } => ElementItem::Func(function_index), |
96 | 23 | _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), |
97 | | }; |
98 | 35.2M | match self.reader.read_operator()? { |
99 | 35.2M | Operator::End => {} |
100 | 14 | _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), |
101 | | } |
102 | 35.2M | Ok(ret) |
103 | | } else { |
104 | 3.34M | self.reader.read_var_u32().map(ElementItem::Func) |
105 | | } |
106 | 38.6M | } |
107 | | } |
108 | | |
109 | | impl<'a> IntoIterator for ElementItemsReader<'a> { |
110 | | type Item = Result<ElementItem>; |
111 | | type IntoIter = ElementItemsIterator<'a>; |
112 | | 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>; |
130 | 0 | fn next(&mut self) -> Option<Self::Item> { |
131 | 0 | if self.err || self.left == 0 { |
132 | 0 | return None; |
133 | 0 | } |
134 | 0 | let result = self.reader.read(); |
135 | 0 | self.err = result.is_err(); |
136 | 0 | self.left -= 1; |
137 | 0 | Some(result) |
138 | 0 | } |
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 | 151k | #[derive(Clone)] |
146 | | pub struct ElementSectionReader<'a> { |
147 | | reader: BinaryReader<'a>, |
148 | | count: u32, |
149 | | } |
150 | | |
151 | | impl<'a> ElementSectionReader<'a> { |
152 | 8.33M | pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> { |
153 | 8.33M | let mut reader = BinaryReader::new_with_offset(data, offset); |
154 | 8.33M | let count = reader.read_var_u32()?; |
155 | 8.33M | Ok(ElementSectionReader { reader, count }) |
156 | 8.33M | } |
157 | | |
158 | 748k | pub fn original_position(&self) -> usize { |
159 | 748k | self.reader.original_position() |
160 | 748k | } |
161 | | |
162 | 4.14M | pub fn get_count(&self) -> u32 { |
163 | 4.14M | self.count |
164 | 4.14M | } |
165 | | |
166 | | /// Reads content of the element section. |
167 | | /// |
168 | | /// # Examples |
169 | | /// |
170 | | /// ```no_run |
171 | | /// # let data: &[u8] = &[]; |
172 | | /// use wasmparser::{ElementSectionReader, ElementKind}; |
173 | | /// let mut element_reader = ElementSectionReader::new(data, 0).unwrap(); |
174 | | /// for _ in 0..element_reader.get_count() { |
175 | | /// let element = element_reader.read().expect("element"); |
176 | | /// if let ElementKind::Active { init_expr, .. } = element.kind { |
177 | | /// let mut init_expr_reader = init_expr.get_binary_reader(); |
178 | | /// let op = init_expr_reader.read_operator().expect("op"); |
179 | | /// println!("Init const: {:?}", op); |
180 | | /// } |
181 | | /// let mut items_reader = element.items.get_items_reader().expect("items reader"); |
182 | | /// for _ in 0..items_reader.get_count() { |
183 | | /// let item = items_reader.read().expect("item"); |
184 | | /// println!(" Item: {:?}", item); |
185 | | /// } |
186 | | /// } |
187 | | /// ``` |
188 | 870k | pub fn read<'b>(&mut self) -> Result<Element<'b>> |
189 | 870k | where |
190 | 870k | 'a: 'b, |
191 | 870k | { |
192 | 870k | let flags = self.reader.read_var_u32()?; |
193 | 869k | if (flags & !0b111) != 0 { |
194 | 873 | return Err(BinaryReaderError::new( |
195 | 873 | "invalid flags byte in element segment", |
196 | 873 | self.reader.original_position() - 1, |
197 | 873 | )); |
198 | 868k | } |
199 | 868k | let kind = if flags & 0b001 != 0 { |
200 | 558k | if flags & 0b010 != 0 { |
201 | 213k | ElementKind::Declared |
202 | | } else { |
203 | 345k | ElementKind::Passive |
204 | | } |
205 | | } else { |
206 | 310k | let table_index = if flags & 0b010 == 0 { |
207 | 242k | 0 |
208 | | } else { |
209 | 67.2k | self.reader.read_var_u32()? |
210 | | }; |
211 | 303k | let init_expr = { |
212 | 310k | let expr_offset = self.reader.position; |
213 | 310k | self.reader.skip_init_expr()?; |
214 | 303k | let data = &self.reader.buffer[expr_offset..self.reader.position]; |
215 | 303k | InitExpr::new(data, self.reader.original_offset + expr_offset) |
216 | 303k | }; |
217 | 303k | ElementKind::Active { |
218 | 303k | table_index, |
219 | 303k | init_expr, |
220 | 303k | } |
221 | | }; |
222 | 862k | let exprs = flags & 0b100 != 0; |
223 | 862k | let ty = if flags & 0b011 != 0 { |
224 | 625k | if exprs { |
225 | 579k | self.reader.read_type()? |
226 | | } else { |
227 | 46.3k | match self.reader.read_external_kind()? { |
228 | 46.1k | ExternalKind::Function => Type::FuncRef, |
229 | | _ => { |
230 | 31 | return Err(BinaryReaderError::new( |
231 | 31 | "only the function external type is supported in elem segment", |
232 | 31 | self.reader.original_position() - 1, |
233 | 31 | )); |
234 | | } |
235 | | } |
236 | | } |
237 | | } else { |
238 | 236k | Type::FuncRef |
239 | | }; |
240 | 862k | let data_start = self.reader.position; |
241 | 862k | let items_count = self.reader.read_var_u32()?; |
242 | 862k | if exprs { |
243 | 35.2M | for _ in 0..items_count { |
244 | 35.2M | self.reader.skip_init_expr()?; |
245 | | } |
246 | | } else { |
247 | 3.36M | for _ in 0..items_count { |
248 | 3.36M | self.reader.skip_var_32()?; |
249 | | } |
250 | | } |
251 | 861k | let data_end = self.reader.position; |
252 | 861k | let items = ElementItems { |
253 | 861k | offset: self.reader.original_offset + data_start, |
254 | 861k | data: &self.reader.buffer[data_start..data_end], |
255 | 861k | exprs, |
256 | 861k | }; |
257 | 861k | Ok(Element { kind, items, ty }) |
258 | 870k | } |
259 | | } |
260 | | |
261 | | impl<'a> SectionReader for ElementSectionReader<'a> { |
262 | | type Item = Element<'a>; |
263 | 870k | fn read(&mut self) -> Result<Self::Item> { |
264 | 870k | ElementSectionReader::read(self) |
265 | 870k | } |
266 | 4.13M | fn eof(&self) -> bool { |
267 | 4.13M | self.reader.eof() |
268 | 4.13M | } |
269 | 748k | fn original_position(&self) -> usize { |
270 | 748k | ElementSectionReader::original_position(self) |
271 | 748k | } |
272 | 299k | fn range(&self) -> Range { |
273 | 299k | self.reader.range() |
274 | 299k | } |
275 | | } |
276 | | |
277 | | impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> { |
278 | 4.14M | fn get_count(&self) -> u32 { |
279 | 4.14M | ElementSectionReader::get_count(self) |
280 | 4.14M | } |
281 | | } |
282 | | |
283 | | impl<'a> IntoIterator for ElementSectionReader<'a> { |
284 | | type Item = Result<Element<'a>>; |
285 | | type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>; |
286 | | |
287 | 3.99M | fn into_iter(self) -> Self::IntoIter { |
288 | 3.99M | SectionIteratorLimited::new(self) |
289 | 3.99M | } |
290 | | } |