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 std::convert::TryInto;
17 use std::fmt;
18 use std::str;
19
20 use crate::limits::*;
21
22 use crate::primitives::{
23 BinaryReaderError, BrTable, CustomSectionKind, ExternalKind, FuncType, GlobalType, Ieee32,
24 Ieee64, LinkingType, MemoryImmediate, MemoryType, NameType, Operator, RelocType,
25 ResizableLimits, ResizableLimits64, Result, SIMDLaneIndex, SectionCode, TableType, Type,
26 TypeOrFuncType, V128,
27 };
28 use crate::{EventType, ExportType, Import, ImportSectionEntryType, InstanceType, ModuleType};
29
30 const MAX_WASM_BR_TABLE_SIZE: usize = MAX_WASM_FUNCTION_SIZE;
31
is_name(name: &str, expected: &'static str) -> bool32 fn is_name(name: &str, expected: &'static str) -> bool {
33 name == expected
34 }
35
is_name_prefix(name: &str, prefix: &'static str) -> bool36 fn is_name_prefix(name: &str, prefix: &'static str) -> bool {
37 name.starts_with(prefix)
38 }
39
40 const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
41 const WASM_EXPERIMENTAL_VERSION: u32 = 0xd;
42 const WASM_SUPPORTED_VERSION: u32 = 0x1;
43
44 #[derive(Clone)]
45 pub(crate) struct SectionHeader<'a> {
46 pub code: SectionCode<'a>,
47 pub payload_start: usize,
48 pub payload_len: usize,
49 }
50
51 /// Bytecode range in the WebAssembly module.
52 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
53 pub struct Range {
54 /// The start bound of the range.
55 pub start: usize,
56 /// The end bound of the range.
57 pub end: usize,
58 }
59
60 impl Range {
61 /// Constructs a new instance of `Range`.
62 ///
63 /// # Panics
64 /// If `start` is greater than `end`.
new(start: usize, end: usize) -> Range65 pub fn new(start: usize, end: usize) -> Range {
66 assert!(start <= end);
67 Range { start, end }
68 }
69
70 /// Returns a new slice between `start` and `end - 1` from `data`.
slice<'a>(&self, data: &'a [u8]) -> &'a [u8]71 pub fn slice<'a>(&self, data: &'a [u8]) -> &'a [u8] {
72 &data[self.start..self.end]
73 }
74 }
75
76 /// A binary reader of the WebAssembly structures and types.
77 #[derive(Clone, Debug, Hash)]
78 pub struct BinaryReader<'a> {
79 pub(crate) buffer: &'a [u8],
80 pub(crate) position: usize,
81 pub(crate) original_offset: usize,
82 }
83
84 impl<'a> BinaryReader<'a> {
85 /// Constructs `BinaryReader` type.
86 ///
87 /// # Examples
88 /// ```
89 /// let fn_body = &vec![0x41, 0x00, 0x10, 0x00, 0x0B];
90 /// let mut reader = wasmparser::BinaryReader::new(fn_body);
91 /// while !reader.eof() {
92 /// let op = reader.read_operator();
93 /// println!("{:?}", op)
94 /// }
95 /// ```
new(data: &[u8]) -> BinaryReader96 pub fn new(data: &[u8]) -> BinaryReader {
97 BinaryReader {
98 buffer: data,
99 position: 0,
100 original_offset: 0,
101 }
102 }
103
104 /// Constructs a `BinaryReader` with an explicit starting offset.
new_with_offset(data: &[u8], original_offset: usize) -> BinaryReader105 pub fn new_with_offset(data: &[u8], original_offset: usize) -> BinaryReader {
106 BinaryReader {
107 buffer: data,
108 position: 0,
109 original_offset,
110 }
111 }
112
original_position(&self) -> usize113 pub fn original_position(&self) -> usize {
114 self.original_offset + self.position
115 }
116
117 /// Returns a range from the starting offset to the end of the buffer.
range(&self) -> Range118 pub fn range(&self) -> Range {
119 Range {
120 start: self.original_offset,
121 end: self.original_offset + self.buffer.len(),
122 }
123 }
124
remaining_buffer(&self) -> &'a [u8]125 pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
126 &self.buffer[self.position..]
127 }
128
ensure_has_byte(&self) -> Result<()>129 fn ensure_has_byte(&self) -> Result<()> {
130 if self.position < self.buffer.len() {
131 Ok(())
132 } else {
133 Err(BinaryReaderError::eof(self.original_position(), 1))
134 }
135 }
136
ensure_has_bytes(&self, len: usize) -> Result<()>137 pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
138 if self.position + len <= self.buffer.len() {
139 Ok(())
140 } else {
141 let hint = self.position + len - self.buffer.len();
142 Err(BinaryReaderError::eof(self.original_position(), hint))
143 }
144 }
145
read_var_u1(&mut self) -> Result<u32>146 fn read_var_u1(&mut self) -> Result<u32> {
147 let b = self.read_u8()?;
148 if (b & 0xFE) != 0 {
149 return Err(BinaryReaderError::new(
150 "Invalid var_u1",
151 self.original_position() - 1,
152 ));
153 }
154 Ok(b)
155 }
156
read_var_i7(&mut self) -> Result<i32>157 fn read_var_i7(&mut self) -> Result<i32> {
158 let b = self.read_u8()?;
159 if (b & 0x80) != 0 {
160 return Err(BinaryReaderError::new(
161 "Invalid var_i7",
162 self.original_position() - 1,
163 ));
164 }
165 Ok((b << 25) as i32 >> 25)
166 }
167
read_var_u7(&mut self) -> Result<u32>168 pub(crate) fn read_var_u7(&mut self) -> Result<u32> {
169 let b = self.read_u8()?;
170 if (b & 0x80) != 0 {
171 return Err(BinaryReaderError::new(
172 "Invalid var_u7",
173 self.original_position() - 1,
174 ));
175 }
176 Ok(b)
177 }
178
read_type(&mut self) -> Result<Type>179 pub fn read_type(&mut self) -> Result<Type> {
180 let code = self.read_var_i7()?;
181 match code {
182 -0x01 => Ok(Type::I32),
183 -0x02 => Ok(Type::I64),
184 -0x03 => Ok(Type::F32),
185 -0x04 => Ok(Type::F64),
186 -0x05 => Ok(Type::V128),
187 -0x10 => Ok(Type::FuncRef),
188 -0x11 => Ok(Type::ExternRef),
189 -0x18 => Ok(Type::ExnRef),
190 -0x20 => Ok(Type::Func),
191 -0x40 => Ok(Type::EmptyBlockType),
192 _ => Err(BinaryReaderError::new(
193 "Invalid type",
194 self.original_position() - 1,
195 )),
196 }
197 }
198
read_external_kind(&mut self) -> Result<ExternalKind>199 pub(crate) fn read_external_kind(&mut self) -> Result<ExternalKind> {
200 let code = self.read_u8()?;
201 match code {
202 0 => Ok(ExternalKind::Function),
203 1 => Ok(ExternalKind::Table),
204 2 => Ok(ExternalKind::Memory),
205 3 => Ok(ExternalKind::Global),
206 4 => Ok(ExternalKind::Event),
207 5 => Ok(ExternalKind::Module),
208 6 => Ok(ExternalKind::Instance),
209 7 => Ok(ExternalKind::Type),
210 _ => Err(BinaryReaderError::new(
211 "Invalid external kind",
212 self.original_position() - 1,
213 )),
214 }
215 }
216
read_func_type(&mut self) -> Result<FuncType>217 pub(crate) fn read_func_type(&mut self) -> Result<FuncType> {
218 let params_len = self.read_var_u32()? as usize;
219 if params_len > MAX_WASM_FUNCTION_PARAMS {
220 return Err(BinaryReaderError::new(
221 "function params size is out of bound",
222 self.original_position() - 1,
223 ));
224 }
225 let mut params: Vec<Type> = Vec::with_capacity(params_len);
226 for _ in 0..params_len {
227 params.push(self.read_type()?);
228 }
229 let returns_len = self.read_var_u32()? as usize;
230 if returns_len > MAX_WASM_FUNCTION_RETURNS {
231 return Err(BinaryReaderError::new(
232 "function returns size is out of bound",
233 self.original_position() - 1,
234 ));
235 }
236 let mut returns: Vec<Type> = Vec::with_capacity(returns_len);
237 for _ in 0..returns_len {
238 returns.push(self.read_type()?);
239 }
240 Ok(FuncType {
241 params: params.into_boxed_slice(),
242 returns: returns.into_boxed_slice(),
243 })
244 }
245
read_module_type(&mut self) -> Result<ModuleType<'a>>246 pub(crate) fn read_module_type(&mut self) -> Result<ModuleType<'a>> {
247 let pos = self.original_position();
248 let imports_len = self.read_var_u32()? as usize;
249 if imports_len > MAX_WASM_IMPORTS {
250 return Err(BinaryReaderError::new("imports size is out of bounds", pos));
251 }
252 Ok(ModuleType {
253 imports: (0..imports_len)
254 .map(|_| self.read_import())
255 .collect::<Result<_>>()?,
256 exports: self.read_export_types()?,
257 })
258 }
259
read_instance_type(&mut self) -> Result<InstanceType<'a>>260 pub(crate) fn read_instance_type(&mut self) -> Result<InstanceType<'a>> {
261 Ok(InstanceType {
262 exports: self.read_export_types()?,
263 })
264 }
265
read_export_types(&mut self) -> Result<Box<[ExportType<'a>]>>266 fn read_export_types(&mut self) -> Result<Box<[ExportType<'a>]>> {
267 let pos = self.original_position();
268 let exports_len = self.read_var_u32()? as usize;
269 if exports_len > MAX_WASM_EXPORTS {
270 return Err(BinaryReaderError::new("exports size is out of bound", pos));
271 }
272 (0..exports_len).map(|_| self.read_export_type()).collect()
273 }
274
read_import(&mut self) -> Result<Import<'a>>275 pub(crate) fn read_import(&mut self) -> Result<Import<'a>> {
276 let module = self.read_string()?;
277 let field = self.read_string()?;
278
279 // For the `field`, figure out if we're the experimental encoding of
280 // single-level imports for the module linking proposal (a single-byte
281 // string which is 0xc0, which is invalid utf-8) or if we have a second
282 // level of import.
283 let field = if field.is_empty() && self.buffer.get(self.position) == Some(&0xff) {
284 self.position += 1;
285 None
286 } else {
287 Some(field)
288 };
289
290 let ty = self.read_import_desc()?;
291 Ok(Import { module, field, ty })
292 }
293
read_export_type(&mut self) -> Result<ExportType<'a>>294 pub(crate) fn read_export_type(&mut self) -> Result<ExportType<'a>> {
295 let name = self.read_string()?;
296 let ty = self.read_import_desc()?;
297 Ok(ExportType { name, ty })
298 }
299
read_import_desc(&mut self) -> Result<ImportSectionEntryType>300 pub(crate) fn read_import_desc(&mut self) -> Result<ImportSectionEntryType> {
301 Ok(match self.read_external_kind()? {
302 ExternalKind::Function => ImportSectionEntryType::Function(self.read_var_u32()?),
303 ExternalKind::Table => ImportSectionEntryType::Table(self.read_table_type()?),
304 ExternalKind::Memory => ImportSectionEntryType::Memory(self.read_memory_type()?),
305 ExternalKind::Event => ImportSectionEntryType::Event(self.read_event_type()?),
306 ExternalKind::Global => ImportSectionEntryType::Global(self.read_global_type()?),
307 ExternalKind::Module => ImportSectionEntryType::Module(self.read_var_u32()?),
308 ExternalKind::Instance => ImportSectionEntryType::Instance(self.read_var_u32()?),
309 ExternalKind::Type => {
310 return Err(BinaryReaderError::new(
311 "cannot import types",
312 self.original_position() - 1,
313 ))
314 }
315 })
316 }
317
read_resizable_limits(&mut self, max_present: bool) -> Result<ResizableLimits>318 fn read_resizable_limits(&mut self, max_present: bool) -> Result<ResizableLimits> {
319 let initial = self.read_var_u32()?;
320 let maximum = if max_present {
321 Some(self.read_var_u32()?)
322 } else {
323 None
324 };
325 Ok(ResizableLimits { initial, maximum })
326 }
327
read_resizable_limits64(&mut self, max_present: bool) -> Result<ResizableLimits64>328 fn read_resizable_limits64(&mut self, max_present: bool) -> Result<ResizableLimits64> {
329 let initial = self.read_var_u64()?;
330 let maximum = if max_present {
331 Some(self.read_var_u64()?)
332 } else {
333 None
334 };
335 Ok(ResizableLimits64 { initial, maximum })
336 }
337
read_table_type(&mut self) -> Result<TableType>338 pub(crate) fn read_table_type(&mut self) -> Result<TableType> {
339 let element_type = self.read_type()?;
340 let flags = self.read_var_u32()?;
341 if (flags & !0x1) != 0 {
342 return Err(BinaryReaderError::new(
343 "invalid table resizable limits flags",
344 self.original_position() - 1,
345 ));
346 }
347 let limits = self.read_resizable_limits((flags & 0x1) != 0)?;
348 Ok(TableType {
349 element_type,
350 limits,
351 })
352 }
353
read_memory_type(&mut self) -> Result<MemoryType>354 pub(crate) fn read_memory_type(&mut self) -> Result<MemoryType> {
355 let pos = self.original_position();
356 let flags = self.read_u8()?;
357 if (flags & !0x7) != 0 {
358 return Err(BinaryReaderError::new(
359 "invalid table resizable limits flags",
360 pos,
361 ));
362 }
363 if flags & 0x4 == 0 {
364 let limits = self.read_resizable_limits((flags & 0x1) != 0)?;
365 let shared = (flags & 0x2) != 0;
366 Ok(MemoryType::M32 { limits, shared })
367 } else {
368 let limits = self.read_resizable_limits64((flags & 0x1) != 0)?;
369 let shared = (flags & 0x2) != 0;
370 Ok(MemoryType::M64 { limits, shared })
371 }
372 }
373
read_event_type(&mut self) -> Result<EventType>374 pub(crate) fn read_event_type(&mut self) -> Result<EventType> {
375 let attribute = self.read_var_u32()?;
376 if attribute != 0 {
377 return Err(BinaryReaderError::new(
378 "invalid event attributes",
379 self.original_position() - 1,
380 ));
381 }
382 let type_index = self.read_var_u32()?;
383 Ok(EventType { type_index })
384 }
385
read_global_type(&mut self) -> Result<GlobalType>386 pub(crate) fn read_global_type(&mut self) -> Result<GlobalType> {
387 Ok(GlobalType {
388 content_type: self.read_type()?,
389 mutable: self.read_var_u1()? != 0,
390 })
391 }
392
read_first_byte_and_var_u32(&mut self) -> Result<(u8, u32)>393 fn read_first_byte_and_var_u32(&mut self) -> Result<(u8, u32)> {
394 let pos = self.position;
395 let val = self.read_var_u32()?;
396 Ok((self.buffer[pos], val))
397 }
398
read_memarg(&mut self) -> Result<MemoryImmediate>399 fn read_memarg(&mut self) -> Result<MemoryImmediate> {
400 let flags_pos = self.original_position();
401 let mut flags = self.read_var_u32()?;
402 let offset = self.read_var_u32()?;
403 let memory = if flags & (1 << 6) != 0 {
404 flags ^= 1 << 6;
405 self.read_var_u32()?
406 } else {
407 0
408 };
409 let align = if flags >= (1 << 6) {
410 return Err(BinaryReaderError::new("alignment too large", flags_pos));
411 } else {
412 flags as u8
413 };
414 Ok(MemoryImmediate {
415 align,
416 offset,
417 memory,
418 })
419 }
420
read_section_code(&mut self, id: u32, offset: usize) -> Result<SectionCode<'a>>421 pub(crate) fn read_section_code(&mut self, id: u32, offset: usize) -> Result<SectionCode<'a>> {
422 match id {
423 0 => {
424 let name = self.read_string()?;
425 let kind = if is_name(name, "name") {
426 CustomSectionKind::Name
427 } else if is_name(name, "producers") {
428 CustomSectionKind::Producers
429 } else if is_name(name, "sourceMappingURL") {
430 CustomSectionKind::SourceMappingURL
431 } else if is_name_prefix(name, "reloc.") {
432 CustomSectionKind::Reloc
433 } else if is_name(name, "linking") {
434 CustomSectionKind::Linking
435 } else {
436 CustomSectionKind::Unknown
437 };
438 Ok(SectionCode::Custom { name, kind })
439 }
440 1 => Ok(SectionCode::Type),
441 2 => Ok(SectionCode::Import),
442 3 => Ok(SectionCode::Function),
443 4 => Ok(SectionCode::Table),
444 5 => Ok(SectionCode::Memory),
445 6 => Ok(SectionCode::Global),
446 7 => Ok(SectionCode::Export),
447 8 => Ok(SectionCode::Start),
448 9 => Ok(SectionCode::Element),
449 10 => Ok(SectionCode::Code),
450 11 => Ok(SectionCode::Data),
451 12 => Ok(SectionCode::DataCount),
452 13 => Ok(SectionCode::Event),
453 14 => Ok(SectionCode::Module),
454 15 => Ok(SectionCode::Instance),
455 16 => Ok(SectionCode::Alias),
456 17 => Ok(SectionCode::ModuleCode),
457 _ => Err(BinaryReaderError::new("Invalid section code", offset)),
458 }
459 }
460
read_br_table(&mut self) -> Result<BrTable<'a>>461 fn read_br_table(&mut self) -> Result<BrTable<'a>> {
462 let targets_len = self.read_var_u32()? as usize;
463 if targets_len > MAX_WASM_BR_TABLE_SIZE {
464 return Err(BinaryReaderError::new(
465 "br_table size is out of bound",
466 self.original_position() - 1,
467 ));
468 }
469 let start = self.position;
470 for _ in 0..targets_len {
471 self.skip_var_32()?;
472 }
473 self.skip_var_32()?;
474 let end = self.position;
475 Ok(BrTable {
476 reader: BinaryReader::new_with_offset(&self.buffer[start..end], start),
477 cnt: targets_len as usize,
478 })
479 }
480
481 /// Returns whether the `BinaryReader` has reached the end of the file.
eof(&self) -> bool482 pub fn eof(&self) -> bool {
483 self.position >= self.buffer.len()
484 }
485
486 /// Returns the `BinaryReader`'s current position.
current_position(&self) -> usize487 pub fn current_position(&self) -> usize {
488 self.position
489 }
490
491 /// Returns the number of bytes remaining in the `BinaryReader`.
bytes_remaining(&self) -> usize492 pub fn bytes_remaining(&self) -> usize {
493 self.buffer.len() - self.position
494 }
495
496 /// Advances the `BinaryReader` `size` bytes, and returns a slice from the
497 /// current position of `size` length.
498 ///
499 /// # Errors
500 /// If `size` exceeds the remaining length in `BinaryReader`.
read_bytes(&mut self, size: usize) -> Result<&'a [u8]>501 pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
502 self.ensure_has_bytes(size)?;
503 let start = self.position;
504 self.position += size;
505 Ok(&self.buffer[start..self.position])
506 }
507
508 /// Advances the `BinaryReader` four bytes and returns a `u32`.
509 /// # Errors
510 /// If `BinaryReader` has less than four bytes remaining.
read_u32(&mut self) -> Result<u32>511 pub fn read_u32(&mut self) -> Result<u32> {
512 self.ensure_has_bytes(4)?;
513 let word = u32::from_le_bytes(
514 self.buffer[self.position..self.position + 4]
515 .try_into()
516 .unwrap(),
517 );
518 self.position += 4;
519 Ok(word)
520 }
521
522 /// Advances the `BinaryReader` eight bytes and returns a `u64`.
523 /// # Errors
524 /// If `BinaryReader` has less than eight bytes remaining.
read_u64(&mut self) -> Result<u64>525 pub fn read_u64(&mut self) -> Result<u64> {
526 self.ensure_has_bytes(8)?;
527 let word = u64::from_le_bytes(
528 self.buffer[self.position..self.position + 8]
529 .try_into()
530 .unwrap(),
531 );
532 self.position += 8;
533 Ok(word)
534 }
535
536 /// Advances the `BinaryReader` a single byte, and returns the data as
537 /// a `u32`.
538 ///
539 /// # Errors
540 ///
541 /// If `BinaryReader` has no bytes remaining.
read_u8(&mut self) -> Result<u32>542 pub fn read_u8(&mut self) -> Result<u32> {
543 self.ensure_has_byte()?;
544 let b = u32::from(self.buffer[self.position]);
545 self.position += 1;
546 Ok(b)
547 }
548
549 /// Advances the `BinaryReader` up to two bytes to parse a variable
550 /// length integer as a `u8`.
551 ///
552 /// # Errors
553 ///
554 /// If `BinaryReader` has less than one or two bytes remaining, or the
555 /// integer is larger than eight bits.
read_var_u8(&mut self) -> Result<u32>556 pub fn read_var_u8(&mut self) -> Result<u32> {
557 // Optimization for single byte i32.
558 let byte = self.read_u8()?;
559 if (byte & 0x80) == 0 {
560 return Ok(byte);
561 }
562
563 let result = (self.read_u8()? << 7) | (byte & 0x7F);
564 if result >= 0x100 {
565 return Err(BinaryReaderError::new(
566 "Invalid var_u8",
567 self.original_position() - 1,
568 ));
569 }
570 Ok(result)
571 }
572
573 /// Advances the `BinaryReader` up to four bytes to parse a variable
574 /// length integer as a `u32`.
575 ///
576 /// # Errors
577 ///
578 /// If `BinaryReader` has less than one or up to four bytes remaining, or
579 /// the integer is larger than 32 bits.
read_var_u32(&mut self) -> Result<u32>580 pub fn read_var_u32(&mut self) -> Result<u32> {
581 // Optimization for single byte i32.
582 let byte = self.read_u8()?;
583 if (byte & 0x80) == 0 {
584 return Ok(byte);
585 }
586
587 let mut result = byte & 0x7F;
588 let mut shift = 7;
589 loop {
590 let byte = self.read_u8()?;
591 result |= ((byte & 0x7F) as u32) << shift;
592 if shift >= 25 && (byte >> (32 - shift)) != 0 {
593 // The continuation bit or unused bits are set.
594 return Err(BinaryReaderError::new(
595 "Invalid var_u32",
596 self.original_position() - 1,
597 ));
598 }
599 shift += 7;
600 if (byte & 0x80) == 0 {
601 break;
602 }
603 }
604 Ok(result)
605 }
606
607 /// Advances the `BinaryReader` up to four bytes to parse a variable
608 /// length integer as a `u64`.
609 ///
610 /// # Errors
611 ///
612 /// If `BinaryReader` has less than one or up to eight bytes remaining, or
613 /// the integer is larger than 64 bits.
read_var_u64(&mut self) -> Result<u64>614 pub fn read_var_u64(&mut self) -> Result<u64> {
615 // Optimization for single byte u64.
616 let byte = u64::from(self.read_u8()?);
617 if (byte & 0x80) == 0 {
618 return Ok(byte);
619 }
620
621 let mut result = byte & 0x7F;
622 let mut shift = 7;
623 loop {
624 let byte = u64::from(self.read_u8()?);
625 result |= (byte & 0x7F) << shift;
626 if shift >= 57 && (byte >> (64 - shift)) != 0 {
627 // The continuation bit or unused bits are set.
628 return Err(BinaryReaderError::new(
629 "Invalid var_u64",
630 self.original_position() - 1,
631 ));
632 }
633 shift += 7;
634 if (byte & 0x80) == 0 {
635 break;
636 }
637 }
638 Ok(result)
639 }
640
641 /// Advances the `BinaryReader` up to four bytes over a variable length 32
642 /// bit integer, discarding the result.
643 /// # Errors
644 /// If `BinaryReader` has less than one or up to four bytes remaining, or
645 /// the integer is larger than 32 bits.
skip_var_32(&mut self) -> Result<()>646 pub fn skip_var_32(&mut self) -> Result<()> {
647 for _ in 0..5 {
648 let byte = self.read_u8()?;
649 if (byte & 0x80) == 0 {
650 return Ok(());
651 }
652 }
653 Err(BinaryReaderError::new(
654 "Invalid var_32",
655 self.original_position() - 1,
656 ))
657 }
658
659 /// Alias method for `BinaryReader::skip_var_u32`.
skip_type(&mut self) -> Result<()>660 pub fn skip_type(&mut self) -> Result<()> {
661 self.skip_var_32()
662 }
663
664 /// Advances the `BinaryReader` `len` bytes, skipping the result.
665 /// # Errors
666 /// If `BinaryReader` has less than `len` bytes remaining.
skip_bytes(&mut self, len: usize) -> Result<()>667 pub fn skip_bytes(&mut self, len: usize) -> Result<()> {
668 self.ensure_has_bytes(len)?;
669 self.position += len;
670 Ok(())
671 }
672
673 /// Advances the `BinaryReader` past a WebAssembly string. This method does
674 /// not perform any utf-8 validation.
675 /// # Errors
676 /// If `BinaryReader` has less than four bytes, the string's length exceeds
677 /// the remaining bytes, or the string length
678 /// exceeds `limits::MAX_WASM_STRING_SIZE`.
skip_string(&mut self) -> Result<()>679 pub fn skip_string(&mut self) -> Result<()> {
680 let len = self.read_var_u32()? as usize;
681 if len > MAX_WASM_STRING_SIZE {
682 return Err(BinaryReaderError::new(
683 "string size out of bounds",
684 self.original_position() - 1,
685 ));
686 }
687 self.skip_bytes(len)
688 }
689
skip_to(&mut self, position: usize)690 pub(crate) fn skip_to(&mut self, position: usize) {
691 assert!(
692 self.position <= position && position <= self.buffer.len(),
693 "skip_to allowed only into region past current position"
694 );
695 self.position = position;
696 }
697
698 /// Advances the `BinaryReader` up to four bytes to parse a variable
699 /// length integer as a `i32`.
700 /// # Errors
701 /// If `BinaryReader` has less than one or up to four bytes remaining, or
702 /// the integer is larger than 32 bits.
read_var_i32(&mut self) -> Result<i32>703 pub fn read_var_i32(&mut self) -> Result<i32> {
704 // Optimization for single byte i32.
705 let byte = self.read_u8()?;
706 if (byte & 0x80) == 0 {
707 return Ok(((byte as i32) << 25) >> 25);
708 }
709
710 let mut result = (byte & 0x7F) as i32;
711 let mut shift = 7;
712 loop {
713 let byte = self.read_u8()?;
714 result |= ((byte & 0x7F) as i32) << shift;
715 if shift >= 25 {
716 let continuation_bit = (byte & 0x80) != 0;
717 let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
718 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
719 return Err(BinaryReaderError::new(
720 "Invalid var_i32",
721 self.original_position() - 1,
722 ));
723 }
724 return Ok(result);
725 }
726 shift += 7;
727 if (byte & 0x80) == 0 {
728 break;
729 }
730 }
731 let ashift = 32 - shift;
732 Ok((result << ashift) >> ashift)
733 }
734
735 /// Advances the `BinaryReader` up to four bytes to parse a variable
736 /// length integer as a signed 33 bit integer, returned as a `i64`.
737 /// # Errors
738 /// If `BinaryReader` has less than one or up to five bytes remaining, or
739 /// the integer is larger than 33 bits.
read_var_s33(&mut self) -> Result<i64>740 pub fn read_var_s33(&mut self) -> Result<i64> {
741 // Optimization for single byte.
742 let byte = self.read_u8()?;
743 if (byte & 0x80) == 0 {
744 return Ok(((byte as i8) << 1) as i64 >> 1);
745 }
746
747 let mut result = (byte & 0x7F) as i64;
748 let mut shift = 7;
749 loop {
750 let byte = self.read_u8()?;
751 result |= ((byte & 0x7F) as i64) << shift;
752 if shift >= 25 {
753 let continuation_bit = (byte & 0x80) != 0;
754 let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
755 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
756 return Err(BinaryReaderError::new(
757 "Invalid var_s33",
758 self.original_position() - 1,
759 ));
760 }
761 return Ok(result);
762 }
763 shift += 7;
764 if (byte & 0x80) == 0 {
765 break;
766 }
767 }
768 let ashift = 64 - shift;
769 Ok((result << ashift) >> ashift)
770 }
771
772 /// Advances the `BinaryReader` up to eight bytes to parse a variable
773 /// length integer as a 64 bit integer, returned as a `i64`.
774 /// # Errors
775 /// If `BinaryReader` has less than one or up to eight bytes remaining, or
776 /// the integer is larger than 64 bits.
read_var_i64(&mut self) -> Result<i64>777 pub fn read_var_i64(&mut self) -> Result<i64> {
778 let mut result: i64 = 0;
779 let mut shift = 0;
780 loop {
781 let byte = self.read_u8()?;
782 result |= i64::from(byte & 0x7F) << shift;
783 if shift >= 57 {
784 let continuation_bit = (byte & 0x80) != 0;
785 let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
786 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
787 return Err(BinaryReaderError::new(
788 "Invalid var_i64",
789 self.original_position() - 1,
790 ));
791 }
792 return Ok(result);
793 }
794 shift += 7;
795 if (byte & 0x80) == 0 {
796 break;
797 }
798 }
799 let ashift = 64 - shift;
800 Ok((result << ashift) >> ashift)
801 }
802
803 /// Advances the `BinaryReader` up to four bytes to parse a variable
804 /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
805 /// # Errors
806 /// If `BinaryReader` has less than one or up to four bytes remaining, or
807 /// the integer is larger than 32 bits.
read_f32(&mut self) -> Result<Ieee32>808 pub fn read_f32(&mut self) -> Result<Ieee32> {
809 let value = self.read_u32()?;
810 Ok(Ieee32(value))
811 }
812
813 /// Advances the `BinaryReader` up to four bytes to parse a variable
814 /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
815 /// # Errors
816 /// If `BinaryReader` has less than one or up to four bytes remaining, or
817 /// the integer is larger than 32 bits.
read_f64(&mut self) -> Result<Ieee64>818 pub fn read_f64(&mut self) -> Result<Ieee64> {
819 let value = self.read_u64()?;
820 Ok(Ieee64(value))
821 }
822
823 /// Reads a WebAssembly string from the module.
824 /// # Errors
825 /// If `BinaryReader` has less than up to four bytes remaining, the string's
826 /// length exceeds the remaining bytes, the string's length exceeds
827 /// `limits::MAX_WASM_STRING_SIZE`, or the string contains invalid utf-8.
read_string(&mut self) -> Result<&'a str>828 pub fn read_string(&mut self) -> Result<&'a str> {
829 let len = self.read_var_u32()? as usize;
830 if len > MAX_WASM_STRING_SIZE {
831 return Err(BinaryReaderError::new(
832 "string size out of bounds",
833 self.original_position() - 1,
834 ));
835 }
836 let bytes = self.read_bytes(len)?;
837 str::from_utf8(bytes).map_err(|_| {
838 BinaryReaderError::new("invalid UTF-8 encoding", self.original_position() - 1)
839 })
840 }
841
read_memarg_of_align(&mut self, max_align: u8) -> Result<MemoryImmediate>842 fn read_memarg_of_align(&mut self, max_align: u8) -> Result<MemoryImmediate> {
843 let align_pos = self.original_position();
844 let imm = self.read_memarg()?;
845 if imm.align > max_align {
846 return Err(BinaryReaderError::new(
847 "alignment must not be larger than natural",
848 align_pos,
849 ));
850 }
851 Ok(imm)
852 }
853
read_0xfe_operator(&mut self) -> Result<Operator<'a>>854 fn read_0xfe_operator(&mut self) -> Result<Operator<'a>> {
855 let code = self.read_var_u32()?;
856 Ok(match code {
857 0x00 => Operator::MemoryAtomicNotify {
858 memarg: self.read_memarg_of_align(2)?,
859 },
860 0x01 => Operator::MemoryAtomicWait32 {
861 memarg: self.read_memarg_of_align(2)?,
862 },
863 0x02 => Operator::MemoryAtomicWait64 {
864 memarg: self.read_memarg_of_align(3)?,
865 },
866 0x03 => Operator::AtomicFence {
867 flags: self.read_u8()? as u8,
868 },
869 0x10 => Operator::I32AtomicLoad {
870 memarg: self.read_memarg_of_align(2)?,
871 },
872 0x11 => Operator::I64AtomicLoad {
873 memarg: self.read_memarg_of_align(3)?,
874 },
875 0x12 => Operator::I32AtomicLoad8U {
876 memarg: self.read_memarg_of_align(0)?,
877 },
878 0x13 => Operator::I32AtomicLoad16U {
879 memarg: self.read_memarg_of_align(1)?,
880 },
881 0x14 => Operator::I64AtomicLoad8U {
882 memarg: self.read_memarg_of_align(0)?,
883 },
884 0x15 => Operator::I64AtomicLoad16U {
885 memarg: self.read_memarg_of_align(1)?,
886 },
887 0x16 => Operator::I64AtomicLoad32U {
888 memarg: self.read_memarg_of_align(2)?,
889 },
890 0x17 => Operator::I32AtomicStore {
891 memarg: self.read_memarg_of_align(2)?,
892 },
893 0x18 => Operator::I64AtomicStore {
894 memarg: self.read_memarg_of_align(3)?,
895 },
896 0x19 => Operator::I32AtomicStore8 {
897 memarg: self.read_memarg_of_align(0)?,
898 },
899 0x1a => Operator::I32AtomicStore16 {
900 memarg: self.read_memarg_of_align(1)?,
901 },
902 0x1b => Operator::I64AtomicStore8 {
903 memarg: self.read_memarg_of_align(0)?,
904 },
905 0x1c => Operator::I64AtomicStore16 {
906 memarg: self.read_memarg_of_align(1)?,
907 },
908 0x1d => Operator::I64AtomicStore32 {
909 memarg: self.read_memarg_of_align(2)?,
910 },
911 0x1e => Operator::I32AtomicRmwAdd {
912 memarg: self.read_memarg_of_align(2)?,
913 },
914 0x1f => Operator::I64AtomicRmwAdd {
915 memarg: self.read_memarg_of_align(3)?,
916 },
917 0x20 => Operator::I32AtomicRmw8AddU {
918 memarg: self.read_memarg_of_align(0)?,
919 },
920 0x21 => Operator::I32AtomicRmw16AddU {
921 memarg: self.read_memarg_of_align(1)?,
922 },
923 0x22 => Operator::I64AtomicRmw8AddU {
924 memarg: self.read_memarg_of_align(0)?,
925 },
926 0x23 => Operator::I64AtomicRmw16AddU {
927 memarg: self.read_memarg_of_align(1)?,
928 },
929 0x24 => Operator::I64AtomicRmw32AddU {
930 memarg: self.read_memarg_of_align(2)?,
931 },
932 0x25 => Operator::I32AtomicRmwSub {
933 memarg: self.read_memarg_of_align(2)?,
934 },
935 0x26 => Operator::I64AtomicRmwSub {
936 memarg: self.read_memarg_of_align(3)?,
937 },
938 0x27 => Operator::I32AtomicRmw8SubU {
939 memarg: self.read_memarg_of_align(0)?,
940 },
941 0x28 => Operator::I32AtomicRmw16SubU {
942 memarg: self.read_memarg_of_align(1)?,
943 },
944 0x29 => Operator::I64AtomicRmw8SubU {
945 memarg: self.read_memarg_of_align(0)?,
946 },
947 0x2a => Operator::I64AtomicRmw16SubU {
948 memarg: self.read_memarg_of_align(1)?,
949 },
950 0x2b => Operator::I64AtomicRmw32SubU {
951 memarg: self.read_memarg_of_align(2)?,
952 },
953 0x2c => Operator::I32AtomicRmwAnd {
954 memarg: self.read_memarg_of_align(2)?,
955 },
956 0x2d => Operator::I64AtomicRmwAnd {
957 memarg: self.read_memarg_of_align(3)?,
958 },
959 0x2e => Operator::I32AtomicRmw8AndU {
960 memarg: self.read_memarg_of_align(0)?,
961 },
962 0x2f => Operator::I32AtomicRmw16AndU {
963 memarg: self.read_memarg_of_align(1)?,
964 },
965 0x30 => Operator::I64AtomicRmw8AndU {
966 memarg: self.read_memarg_of_align(0)?,
967 },
968 0x31 => Operator::I64AtomicRmw16AndU {
969 memarg: self.read_memarg_of_align(1)?,
970 },
971 0x32 => Operator::I64AtomicRmw32AndU {
972 memarg: self.read_memarg_of_align(2)?,
973 },
974 0x33 => Operator::I32AtomicRmwOr {
975 memarg: self.read_memarg_of_align(2)?,
976 },
977 0x34 => Operator::I64AtomicRmwOr {
978 memarg: self.read_memarg_of_align(3)?,
979 },
980 0x35 => Operator::I32AtomicRmw8OrU {
981 memarg: self.read_memarg_of_align(0)?,
982 },
983 0x36 => Operator::I32AtomicRmw16OrU {
984 memarg: self.read_memarg_of_align(1)?,
985 },
986 0x37 => Operator::I64AtomicRmw8OrU {
987 memarg: self.read_memarg_of_align(0)?,
988 },
989 0x38 => Operator::I64AtomicRmw16OrU {
990 memarg: self.read_memarg_of_align(1)?,
991 },
992 0x39 => Operator::I64AtomicRmw32OrU {
993 memarg: self.read_memarg_of_align(2)?,
994 },
995 0x3a => Operator::I32AtomicRmwXor {
996 memarg: self.read_memarg_of_align(2)?,
997 },
998 0x3b => Operator::I64AtomicRmwXor {
999 memarg: self.read_memarg_of_align(3)?,
1000 },
1001 0x3c => Operator::I32AtomicRmw8XorU {
1002 memarg: self.read_memarg_of_align(0)?,
1003 },
1004 0x3d => Operator::I32AtomicRmw16XorU {
1005 memarg: self.read_memarg_of_align(1)?,
1006 },
1007 0x3e => Operator::I64AtomicRmw8XorU {
1008 memarg: self.read_memarg_of_align(0)?,
1009 },
1010 0x3f => Operator::I64AtomicRmw16XorU {
1011 memarg: self.read_memarg_of_align(1)?,
1012 },
1013 0x40 => Operator::I64AtomicRmw32XorU {
1014 memarg: self.read_memarg_of_align(2)?,
1015 },
1016 0x41 => Operator::I32AtomicRmwXchg {
1017 memarg: self.read_memarg_of_align(2)?,
1018 },
1019 0x42 => Operator::I64AtomicRmwXchg {
1020 memarg: self.read_memarg_of_align(3)?,
1021 },
1022 0x43 => Operator::I32AtomicRmw8XchgU {
1023 memarg: self.read_memarg_of_align(0)?,
1024 },
1025 0x44 => Operator::I32AtomicRmw16XchgU {
1026 memarg: self.read_memarg_of_align(1)?,
1027 },
1028 0x45 => Operator::I64AtomicRmw8XchgU {
1029 memarg: self.read_memarg_of_align(0)?,
1030 },
1031 0x46 => Operator::I64AtomicRmw16XchgU {
1032 memarg: self.read_memarg_of_align(1)?,
1033 },
1034 0x47 => Operator::I64AtomicRmw32XchgU {
1035 memarg: self.read_memarg_of_align(2)?,
1036 },
1037 0x48 => Operator::I32AtomicRmwCmpxchg {
1038 memarg: self.read_memarg_of_align(2)?,
1039 },
1040 0x49 => Operator::I64AtomicRmwCmpxchg {
1041 memarg: self.read_memarg_of_align(3)?,
1042 },
1043 0x4a => Operator::I32AtomicRmw8CmpxchgU {
1044 memarg: self.read_memarg_of_align(0)?,
1045 },
1046 0x4b => Operator::I32AtomicRmw16CmpxchgU {
1047 memarg: self.read_memarg_of_align(1)?,
1048 },
1049 0x4c => Operator::I64AtomicRmw8CmpxchgU {
1050 memarg: self.read_memarg_of_align(0)?,
1051 },
1052 0x4d => Operator::I64AtomicRmw16CmpxchgU {
1053 memarg: self.read_memarg_of_align(1)?,
1054 },
1055 0x4e => Operator::I64AtomicRmw32CmpxchgU {
1056 memarg: self.read_memarg_of_align(2)?,
1057 },
1058
1059 _ => {
1060 return Err(BinaryReaderError::new(
1061 format!("Unknown 0xfe subopcode: 0x{:x}", code),
1062 self.original_position() - 1,
1063 ));
1064 }
1065 })
1066 }
1067
read_blocktype(&mut self) -> Result<TypeOrFuncType>1068 fn read_blocktype(&mut self) -> Result<TypeOrFuncType> {
1069 let position = self.position;
1070 if let Ok(ty) = self.read_type() {
1071 Ok(TypeOrFuncType::Type(ty))
1072 } else {
1073 self.position = position;
1074 let idx = self.read_var_s33()?;
1075 if idx < 0 || idx > (std::u32::MAX as i64) {
1076 return Err(BinaryReaderError::new("invalid function type", position));
1077 }
1078 Ok(TypeOrFuncType::FuncType(idx as u32))
1079 }
1080 }
1081
1082 /// Reads the next available `Operator`.
1083 /// # Errors
1084 /// If `BinaryReader` has less bytes remaining than required to parse
1085 /// the `Operator`.
read_operator(&mut self) -> Result<Operator<'a>>1086 pub fn read_operator(&mut self) -> Result<Operator<'a>> {
1087 let code = self.read_u8()? as u8;
1088 Ok(match code {
1089 0x00 => Operator::Unreachable,
1090 0x01 => Operator::Nop,
1091 0x02 => Operator::Block {
1092 ty: self.read_blocktype()?,
1093 },
1094 0x03 => Operator::Loop {
1095 ty: self.read_blocktype()?,
1096 },
1097 0x04 => Operator::If {
1098 ty: self.read_blocktype()?,
1099 },
1100 0x05 => Operator::Else,
1101 0x06 => Operator::Try {
1102 ty: self.read_blocktype()?,
1103 },
1104 0x07 => Operator::Catch {
1105 index: self.read_var_u32()?,
1106 },
1107 0x08 => Operator::Throw {
1108 index: self.read_var_u32()?,
1109 },
1110 0x09 => Operator::Rethrow {
1111 relative_depth: self.read_var_u32()?,
1112 },
1113 0x0a => Operator::Unwind,
1114 0x0b => Operator::End,
1115 0x0c => Operator::Br {
1116 relative_depth: self.read_var_u32()?,
1117 },
1118 0x0d => Operator::BrIf {
1119 relative_depth: self.read_var_u32()?,
1120 },
1121 0x0e => Operator::BrTable {
1122 table: self.read_br_table()?,
1123 },
1124 0x0f => Operator::Return,
1125 0x10 => Operator::Call {
1126 function_index: self.read_var_u32()?,
1127 },
1128 0x11 => Operator::CallIndirect {
1129 index: self.read_var_u32()?,
1130 table_index: self.read_var_u32()?,
1131 },
1132 0x12 => Operator::ReturnCall {
1133 function_index: self.read_var_u32()?,
1134 },
1135 0x13 => Operator::ReturnCallIndirect {
1136 index: self.read_var_u32()?,
1137 table_index: self.read_var_u32()?,
1138 },
1139 0x18 => Operator::Delegate {
1140 relative_depth: self.read_var_u32()?,
1141 },
1142 0x19 => Operator::CatchAll,
1143 0x1a => Operator::Drop,
1144 0x1b => Operator::Select,
1145 0x1c => {
1146 let results = self.read_var_u32()?;
1147 if results != 1 {
1148 return Err(BinaryReaderError::new(
1149 "invalid result arity",
1150 self.position,
1151 ));
1152 }
1153 Operator::TypedSelect {
1154 ty: self.read_type()?,
1155 }
1156 }
1157 0x20 => Operator::LocalGet {
1158 local_index: self.read_var_u32()?,
1159 },
1160 0x21 => Operator::LocalSet {
1161 local_index: self.read_var_u32()?,
1162 },
1163 0x22 => Operator::LocalTee {
1164 local_index: self.read_var_u32()?,
1165 },
1166 0x23 => Operator::GlobalGet {
1167 global_index: self.read_var_u32()?,
1168 },
1169 0x24 => Operator::GlobalSet {
1170 global_index: self.read_var_u32()?,
1171 },
1172 0x25 => Operator::TableGet {
1173 table: self.read_var_u32()?,
1174 },
1175 0x26 => Operator::TableSet {
1176 table: self.read_var_u32()?,
1177 },
1178 0x28 => Operator::I32Load {
1179 memarg: self.read_memarg()?,
1180 },
1181 0x29 => Operator::I64Load {
1182 memarg: self.read_memarg()?,
1183 },
1184 0x2a => Operator::F32Load {
1185 memarg: self.read_memarg()?,
1186 },
1187 0x2b => Operator::F64Load {
1188 memarg: self.read_memarg()?,
1189 },
1190 0x2c => Operator::I32Load8S {
1191 memarg: self.read_memarg()?,
1192 },
1193 0x2d => Operator::I32Load8U {
1194 memarg: self.read_memarg()?,
1195 },
1196 0x2e => Operator::I32Load16S {
1197 memarg: self.read_memarg()?,
1198 },
1199 0x2f => Operator::I32Load16U {
1200 memarg: self.read_memarg()?,
1201 },
1202 0x30 => Operator::I64Load8S {
1203 memarg: self.read_memarg()?,
1204 },
1205 0x31 => Operator::I64Load8U {
1206 memarg: self.read_memarg()?,
1207 },
1208 0x32 => Operator::I64Load16S {
1209 memarg: self.read_memarg()?,
1210 },
1211 0x33 => Operator::I64Load16U {
1212 memarg: self.read_memarg()?,
1213 },
1214 0x34 => Operator::I64Load32S {
1215 memarg: self.read_memarg()?,
1216 },
1217 0x35 => Operator::I64Load32U {
1218 memarg: self.read_memarg()?,
1219 },
1220 0x36 => Operator::I32Store {
1221 memarg: self.read_memarg()?,
1222 },
1223 0x37 => Operator::I64Store {
1224 memarg: self.read_memarg()?,
1225 },
1226 0x38 => Operator::F32Store {
1227 memarg: self.read_memarg()?,
1228 },
1229 0x39 => Operator::F64Store {
1230 memarg: self.read_memarg()?,
1231 },
1232 0x3a => Operator::I32Store8 {
1233 memarg: self.read_memarg()?,
1234 },
1235 0x3b => Operator::I32Store16 {
1236 memarg: self.read_memarg()?,
1237 },
1238 0x3c => Operator::I64Store8 {
1239 memarg: self.read_memarg()?,
1240 },
1241 0x3d => Operator::I64Store16 {
1242 memarg: self.read_memarg()?,
1243 },
1244 0x3e => Operator::I64Store32 {
1245 memarg: self.read_memarg()?,
1246 },
1247 0x3f => {
1248 let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
1249 Operator::MemorySize { mem_byte, mem }
1250 }
1251 0x40 => {
1252 let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
1253 Operator::MemoryGrow { mem_byte, mem }
1254 }
1255 0x41 => Operator::I32Const {
1256 value: self.read_var_i32()?,
1257 },
1258 0x42 => Operator::I64Const {
1259 value: self.read_var_i64()?,
1260 },
1261 0x43 => Operator::F32Const {
1262 value: self.read_f32()?,
1263 },
1264 0x44 => Operator::F64Const {
1265 value: self.read_f64()?,
1266 },
1267 0x45 => Operator::I32Eqz,
1268 0x46 => Operator::I32Eq,
1269 0x47 => Operator::I32Ne,
1270 0x48 => Operator::I32LtS,
1271 0x49 => Operator::I32LtU,
1272 0x4a => Operator::I32GtS,
1273 0x4b => Operator::I32GtU,
1274 0x4c => Operator::I32LeS,
1275 0x4d => Operator::I32LeU,
1276 0x4e => Operator::I32GeS,
1277 0x4f => Operator::I32GeU,
1278 0x50 => Operator::I64Eqz,
1279 0x51 => Operator::I64Eq,
1280 0x52 => Operator::I64Ne,
1281 0x53 => Operator::I64LtS,
1282 0x54 => Operator::I64LtU,
1283 0x55 => Operator::I64GtS,
1284 0x56 => Operator::I64GtU,
1285 0x57 => Operator::I64LeS,
1286 0x58 => Operator::I64LeU,
1287 0x59 => Operator::I64GeS,
1288 0x5a => Operator::I64GeU,
1289 0x5b => Operator::F32Eq,
1290 0x5c => Operator::F32Ne,
1291 0x5d => Operator::F32Lt,
1292 0x5e => Operator::F32Gt,
1293 0x5f => Operator::F32Le,
1294 0x60 => Operator::F32Ge,
1295 0x61 => Operator::F64Eq,
1296 0x62 => Operator::F64Ne,
1297 0x63 => Operator::F64Lt,
1298 0x64 => Operator::F64Gt,
1299 0x65 => Operator::F64Le,
1300 0x66 => Operator::F64Ge,
1301 0x67 => Operator::I32Clz,
1302 0x68 => Operator::I32Ctz,
1303 0x69 => Operator::I32Popcnt,
1304 0x6a => Operator::I32Add,
1305 0x6b => Operator::I32Sub,
1306 0x6c => Operator::I32Mul,
1307 0x6d => Operator::I32DivS,
1308 0x6e => Operator::I32DivU,
1309 0x6f => Operator::I32RemS,
1310 0x70 => Operator::I32RemU,
1311 0x71 => Operator::I32And,
1312 0x72 => Operator::I32Or,
1313 0x73 => Operator::I32Xor,
1314 0x74 => Operator::I32Shl,
1315 0x75 => Operator::I32ShrS,
1316 0x76 => Operator::I32ShrU,
1317 0x77 => Operator::I32Rotl,
1318 0x78 => Operator::I32Rotr,
1319 0x79 => Operator::I64Clz,
1320 0x7a => Operator::I64Ctz,
1321 0x7b => Operator::I64Popcnt,
1322 0x7c => Operator::I64Add,
1323 0x7d => Operator::I64Sub,
1324 0x7e => Operator::I64Mul,
1325 0x7f => Operator::I64DivS,
1326 0x80 => Operator::I64DivU,
1327 0x81 => Operator::I64RemS,
1328 0x82 => Operator::I64RemU,
1329 0x83 => Operator::I64And,
1330 0x84 => Operator::I64Or,
1331 0x85 => Operator::I64Xor,
1332 0x86 => Operator::I64Shl,
1333 0x87 => Operator::I64ShrS,
1334 0x88 => Operator::I64ShrU,
1335 0x89 => Operator::I64Rotl,
1336 0x8a => Operator::I64Rotr,
1337 0x8b => Operator::F32Abs,
1338 0x8c => Operator::F32Neg,
1339 0x8d => Operator::F32Ceil,
1340 0x8e => Operator::F32Floor,
1341 0x8f => Operator::F32Trunc,
1342 0x90 => Operator::F32Nearest,
1343 0x91 => Operator::F32Sqrt,
1344 0x92 => Operator::F32Add,
1345 0x93 => Operator::F32Sub,
1346 0x94 => Operator::F32Mul,
1347 0x95 => Operator::F32Div,
1348 0x96 => Operator::F32Min,
1349 0x97 => Operator::F32Max,
1350 0x98 => Operator::F32Copysign,
1351 0x99 => Operator::F64Abs,
1352 0x9a => Operator::F64Neg,
1353 0x9b => Operator::F64Ceil,
1354 0x9c => Operator::F64Floor,
1355 0x9d => Operator::F64Trunc,
1356 0x9e => Operator::F64Nearest,
1357 0x9f => Operator::F64Sqrt,
1358 0xa0 => Operator::F64Add,
1359 0xa1 => Operator::F64Sub,
1360 0xa2 => Operator::F64Mul,
1361 0xa3 => Operator::F64Div,
1362 0xa4 => Operator::F64Min,
1363 0xa5 => Operator::F64Max,
1364 0xa6 => Operator::F64Copysign,
1365 0xa7 => Operator::I32WrapI64,
1366 0xa8 => Operator::I32TruncF32S,
1367 0xa9 => Operator::I32TruncF32U,
1368 0xaa => Operator::I32TruncF64S,
1369 0xab => Operator::I32TruncF64U,
1370 0xac => Operator::I64ExtendI32S,
1371 0xad => Operator::I64ExtendI32U,
1372 0xae => Operator::I64TruncF32S,
1373 0xaf => Operator::I64TruncF32U,
1374 0xb0 => Operator::I64TruncF64S,
1375 0xb1 => Operator::I64TruncF64U,
1376 0xb2 => Operator::F32ConvertI32S,
1377 0xb3 => Operator::F32ConvertI32U,
1378 0xb4 => Operator::F32ConvertI64S,
1379 0xb5 => Operator::F32ConvertI64U,
1380 0xb6 => Operator::F32DemoteF64,
1381 0xb7 => Operator::F64ConvertI32S,
1382 0xb8 => Operator::F64ConvertI32U,
1383 0xb9 => Operator::F64ConvertI64S,
1384 0xba => Operator::F64ConvertI64U,
1385 0xbb => Operator::F64PromoteF32,
1386 0xbc => Operator::I32ReinterpretF32,
1387 0xbd => Operator::I64ReinterpretF64,
1388 0xbe => Operator::F32ReinterpretI32,
1389 0xbf => Operator::F64ReinterpretI64,
1390
1391 0xc0 => Operator::I32Extend8S,
1392 0xc1 => Operator::I32Extend16S,
1393 0xc2 => Operator::I64Extend8S,
1394 0xc3 => Operator::I64Extend16S,
1395 0xc4 => Operator::I64Extend32S,
1396
1397 0xd0 => Operator::RefNull {
1398 ty: self.read_type()?,
1399 },
1400 0xd1 => Operator::RefIsNull,
1401 0xd2 => Operator::RefFunc {
1402 function_index: self.read_var_u32()?,
1403 },
1404
1405 0xfc => self.read_0xfc_operator()?,
1406 0xfd => self.read_0xfd_operator()?,
1407 0xfe => self.read_0xfe_operator()?,
1408
1409 _ => {
1410 return Err(BinaryReaderError::new(
1411 format!("Unknown opcode: 0x{:x}", code),
1412 self.original_position() - 1,
1413 ));
1414 }
1415 })
1416 }
1417
read_0xfc_operator(&mut self) -> Result<Operator<'a>>1418 fn read_0xfc_operator(&mut self) -> Result<Operator<'a>> {
1419 let code = self.read_var_u32()?;
1420 Ok(match code {
1421 0x00 => Operator::I32TruncSatF32S,
1422 0x01 => Operator::I32TruncSatF32U,
1423 0x02 => Operator::I32TruncSatF64S,
1424 0x03 => Operator::I32TruncSatF64U,
1425 0x04 => Operator::I64TruncSatF32S,
1426 0x05 => Operator::I64TruncSatF32U,
1427 0x06 => Operator::I64TruncSatF64S,
1428 0x07 => Operator::I64TruncSatF64U,
1429
1430 0x08 => {
1431 let segment = self.read_var_u32()?;
1432 let mem = self.read_var_u32()?;
1433 Operator::MemoryInit { segment, mem }
1434 }
1435 0x09 => {
1436 let segment = self.read_var_u32()?;
1437 Operator::DataDrop { segment }
1438 }
1439 0x0a => {
1440 let dst = self.read_var_u32()?;
1441 let src = self.read_var_u32()?;
1442 Operator::MemoryCopy { src, dst }
1443 }
1444 0x0b => {
1445 let mem = self.read_var_u32()?;
1446 Operator::MemoryFill { mem }
1447 }
1448 0x0c => {
1449 let segment = self.read_var_u32()?;
1450 let table = self.read_var_u32()?;
1451 Operator::TableInit { segment, table }
1452 }
1453 0x0d => {
1454 let segment = self.read_var_u32()?;
1455 Operator::ElemDrop { segment }
1456 }
1457 0x0e => {
1458 let dst_table = self.read_var_u32()?;
1459 let src_table = self.read_var_u32()?;
1460 Operator::TableCopy {
1461 src_table,
1462 dst_table,
1463 }
1464 }
1465
1466 0x0f => {
1467 let table = self.read_var_u32()?;
1468 Operator::TableGrow { table }
1469 }
1470 0x10 => {
1471 let table = self.read_var_u32()?;
1472 Operator::TableSize { table }
1473 }
1474
1475 0x11 => {
1476 let table = self.read_var_u32()?;
1477 Operator::TableFill { table }
1478 }
1479
1480 _ => {
1481 return Err(BinaryReaderError::new(
1482 format!("Unknown 0xfc subopcode: 0x{:x}", code),
1483 self.original_position() - 1,
1484 ));
1485 }
1486 })
1487 }
1488
read_lane_index(&mut self, max: u32) -> Result<SIMDLaneIndex>1489 fn read_lane_index(&mut self, max: u32) -> Result<SIMDLaneIndex> {
1490 let index = self.read_u8()?;
1491 if index >= max {
1492 return Err(BinaryReaderError::new(
1493 "invalid lane index",
1494 self.original_position() - 1,
1495 ));
1496 }
1497 Ok(index as SIMDLaneIndex)
1498 }
1499
read_v128(&mut self) -> Result<V128>1500 fn read_v128(&mut self) -> Result<V128> {
1501 let mut bytes = [0; 16];
1502 bytes.clone_from_slice(self.read_bytes(16)?);
1503 Ok(V128(bytes))
1504 }
1505
read_0xfd_operator(&mut self) -> Result<Operator<'a>>1506 fn read_0xfd_operator(&mut self) -> Result<Operator<'a>> {
1507 let code = self.read_var_u32()?;
1508 Ok(match code {
1509 0x00 => Operator::V128Load {
1510 memarg: self.read_memarg()?,
1511 },
1512 0x01 => Operator::V128Load8x8S {
1513 memarg: self.read_memarg_of_align(3)?,
1514 },
1515 0x02 => Operator::V128Load8x8U {
1516 memarg: self.read_memarg_of_align(3)?,
1517 },
1518 0x03 => Operator::V128Load16x4S {
1519 memarg: self.read_memarg_of_align(3)?,
1520 },
1521 0x04 => Operator::V128Load16x4U {
1522 memarg: self.read_memarg_of_align(3)?,
1523 },
1524 0x05 => Operator::V128Load32x2S {
1525 memarg: self.read_memarg_of_align(3)?,
1526 },
1527 0x06 => Operator::V128Load32x2U {
1528 memarg: self.read_memarg_of_align(3)?,
1529 },
1530 0x07 => Operator::V128Load8Splat {
1531 memarg: self.read_memarg_of_align(0)?,
1532 },
1533 0x08 => Operator::V128Load16Splat {
1534 memarg: self.read_memarg_of_align(1)?,
1535 },
1536 0x09 => Operator::V128Load32Splat {
1537 memarg: self.read_memarg_of_align(2)?,
1538 },
1539 0x0a => Operator::V128Load64Splat {
1540 memarg: self.read_memarg_of_align(3)?,
1541 },
1542 0x0b => Operator::V128Store {
1543 memarg: self.read_memarg()?,
1544 },
1545 0x0c => Operator::V128Const {
1546 value: self.read_v128()?,
1547 },
1548 0x0d => {
1549 let mut lanes = [0 as SIMDLaneIndex; 16];
1550 for lane in &mut lanes {
1551 *lane = self.read_lane_index(32)?
1552 }
1553 Operator::I8x16Shuffle { lanes }
1554 }
1555 0x0e => Operator::I8x16Swizzle,
1556 0x0f => Operator::I8x16Splat,
1557 0x10 => Operator::I16x8Splat,
1558 0x11 => Operator::I32x4Splat,
1559 0x12 => Operator::I64x2Splat,
1560 0x13 => Operator::F32x4Splat,
1561 0x14 => Operator::F64x2Splat,
1562 0x15 => Operator::I8x16ExtractLaneS {
1563 lane: self.read_lane_index(16)?,
1564 },
1565 0x16 => Operator::I8x16ExtractLaneU {
1566 lane: self.read_lane_index(16)?,
1567 },
1568 0x17 => Operator::I8x16ReplaceLane {
1569 lane: self.read_lane_index(16)?,
1570 },
1571 0x18 => Operator::I16x8ExtractLaneS {
1572 lane: self.read_lane_index(8)?,
1573 },
1574 0x19 => Operator::I16x8ExtractLaneU {
1575 lane: self.read_lane_index(8)?,
1576 },
1577 0x1a => Operator::I16x8ReplaceLane {
1578 lane: self.read_lane_index(8)?,
1579 },
1580 0x1b => Operator::I32x4ExtractLane {
1581 lane: self.read_lane_index(4)?,
1582 },
1583 0x1c => Operator::I32x4ReplaceLane {
1584 lane: self.read_lane_index(4)?,
1585 },
1586 0x1d => Operator::I64x2ExtractLane {
1587 lane: self.read_lane_index(2)?,
1588 },
1589 0x1e => Operator::I64x2ReplaceLane {
1590 lane: self.read_lane_index(2)?,
1591 },
1592 0x1f => Operator::F32x4ExtractLane {
1593 lane: self.read_lane_index(4)?,
1594 },
1595 0x20 => Operator::F32x4ReplaceLane {
1596 lane: self.read_lane_index(4)?,
1597 },
1598 0x21 => Operator::F64x2ExtractLane {
1599 lane: self.read_lane_index(2)?,
1600 },
1601 0x22 => Operator::F64x2ReplaceLane {
1602 lane: self.read_lane_index(2)?,
1603 },
1604 0x23 => Operator::I8x16Eq,
1605 0x24 => Operator::I8x16Ne,
1606 0x25 => Operator::I8x16LtS,
1607 0x26 => Operator::I8x16LtU,
1608 0x27 => Operator::I8x16GtS,
1609 0x28 => Operator::I8x16GtU,
1610 0x29 => Operator::I8x16LeS,
1611 0x2a => Operator::I8x16LeU,
1612 0x2b => Operator::I8x16GeS,
1613 0x2c => Operator::I8x16GeU,
1614 0x2d => Operator::I16x8Eq,
1615 0x2e => Operator::I16x8Ne,
1616 0x2f => Operator::I16x8LtS,
1617 0x30 => Operator::I16x8LtU,
1618 0x31 => Operator::I16x8GtS,
1619 0x32 => Operator::I16x8GtU,
1620 0x33 => Operator::I16x8LeS,
1621 0x34 => Operator::I16x8LeU,
1622 0x35 => Operator::I16x8GeS,
1623 0x36 => Operator::I16x8GeU,
1624 0x37 => Operator::I32x4Eq,
1625 0x38 => Operator::I32x4Ne,
1626 0x39 => Operator::I32x4LtS,
1627 0x3a => Operator::I32x4LtU,
1628 0x3b => Operator::I32x4GtS,
1629 0x3c => Operator::I32x4GtU,
1630 0x3d => Operator::I32x4LeS,
1631 0x3e => Operator::I32x4LeU,
1632 0x3f => Operator::I32x4GeS,
1633 0x40 => Operator::I32x4GeU,
1634 0x41 => Operator::F32x4Eq,
1635 0x42 => Operator::F32x4Ne,
1636 0x43 => Operator::F32x4Lt,
1637 0x44 => Operator::F32x4Gt,
1638 0x45 => Operator::F32x4Le,
1639 0x46 => Operator::F32x4Ge,
1640 0x47 => Operator::F64x2Eq,
1641 0x48 => Operator::F64x2Ne,
1642 0x49 => Operator::F64x2Lt,
1643 0x4a => Operator::F64x2Gt,
1644 0x4b => Operator::F64x2Le,
1645 0x4c => Operator::F64x2Ge,
1646 0x4d => Operator::V128Not,
1647 0x4e => Operator::V128And,
1648 0x4f => Operator::V128AndNot,
1649 0x50 => Operator::V128Or,
1650 0x51 => Operator::V128Xor,
1651 0x52 => Operator::V128Bitselect,
1652 0x53 => Operator::V128AnyTrue,
1653 0x54 => Operator::V128Load8Lane {
1654 memarg: self.read_memarg()?,
1655 lane: self.read_lane_index(16)?,
1656 },
1657 0x55 => Operator::V128Load16Lane {
1658 memarg: self.read_memarg()?,
1659 lane: self.read_lane_index(8)?,
1660 },
1661 0x56 => Operator::V128Load32Lane {
1662 memarg: self.read_memarg()?,
1663 lane: self.read_lane_index(4)?,
1664 },
1665 0x57 => Operator::V128Load64Lane {
1666 memarg: self.read_memarg()?,
1667 lane: self.read_lane_index(2)?,
1668 },
1669 0x58 => Operator::V128Store8Lane {
1670 memarg: self.read_memarg()?,
1671 lane: self.read_lane_index(16)?,
1672 },
1673 0x59 => Operator::V128Store16Lane {
1674 memarg: self.read_memarg()?,
1675 lane: self.read_lane_index(8)?,
1676 },
1677 0x5a => Operator::V128Store32Lane {
1678 memarg: self.read_memarg()?,
1679 lane: self.read_lane_index(4)?,
1680 },
1681 0x5b => Operator::V128Store64Lane {
1682 memarg: self.read_memarg()?,
1683 lane: self.read_lane_index(2)?,
1684 },
1685 0x5c => Operator::V128Load32Zero {
1686 memarg: self.read_memarg_of_align(2)?,
1687 },
1688 0x5d => Operator::V128Load64Zero {
1689 memarg: self.read_memarg_of_align(3)?,
1690 },
1691 0x5e => Operator::F32x4DemoteF64x2Zero,
1692 0x5f => Operator::F64x2PromoteLowF32x4,
1693 0x60 => Operator::I8x16Abs,
1694 0x61 => Operator::I8x16Neg,
1695 0x62 => Operator::I8x16Popcnt,
1696 0x63 => Operator::I8x16AllTrue,
1697 0x64 => Operator::I8x16Bitmask,
1698 0x65 => Operator::I8x16NarrowI16x8S,
1699 0x66 => Operator::I8x16NarrowI16x8U,
1700 0x67 => Operator::F32x4Ceil,
1701 0x68 => Operator::F32x4Floor,
1702 0x69 => Operator::F32x4Trunc,
1703 0x6a => Operator::F32x4Nearest,
1704 0x6b => Operator::I8x16Shl,
1705 0x6c => Operator::I8x16ShrS,
1706 0x6d => Operator::I8x16ShrU,
1707 0x6e => Operator::I8x16Add,
1708 0x6f => Operator::I8x16AddSatS,
1709 0x70 => Operator::I8x16AddSatU,
1710 0x71 => Operator::I8x16Sub,
1711 0x72 => Operator::I8x16SubSatS,
1712 0x73 => Operator::I8x16SubSatU,
1713 0x74 => Operator::F64x2Ceil,
1714 0x75 => Operator::F64x2Floor,
1715 0x76 => Operator::I8x16MinS,
1716 0x77 => Operator::I8x16MinU,
1717 0x78 => Operator::I8x16MaxS,
1718 0x79 => Operator::I8x16MaxU,
1719 0x7a => Operator::F64x2Trunc,
1720 0x7b => Operator::I8x16RoundingAverageU,
1721 0x7c => Operator::I16x8ExtAddPairwiseI8x16S,
1722 0x7d => Operator::I16x8ExtAddPairwiseI8x16U,
1723 0x7e => Operator::I32x4ExtAddPairwiseI16x8S,
1724 0x7f => Operator::I32x4ExtAddPairwiseI16x8U,
1725 0x80 => Operator::I16x8Abs,
1726 0x81 => Operator::I16x8Neg,
1727 0x82 => Operator::I16x8Q15MulrSatS,
1728 0x83 => Operator::I16x8AllTrue,
1729 0x84 => Operator::I16x8Bitmask,
1730 0x85 => Operator::I16x8NarrowI32x4S,
1731 0x86 => Operator::I16x8NarrowI32x4U,
1732 0x87 => Operator::I16x8ExtendLowI8x16S,
1733 0x88 => Operator::I16x8ExtendHighI8x16S,
1734 0x89 => Operator::I16x8ExtendLowI8x16U,
1735 0x8a => Operator::I16x8ExtendHighI8x16U,
1736 0x8b => Operator::I16x8Shl,
1737 0x8c => Operator::I16x8ShrS,
1738 0x8d => Operator::I16x8ShrU,
1739 0x8e => Operator::I16x8Add,
1740 0x8f => Operator::I16x8AddSatS,
1741 0x90 => Operator::I16x8AddSatU,
1742 0x91 => Operator::I16x8Sub,
1743 0x92 => Operator::I16x8SubSatS,
1744 0x93 => Operator::I16x8SubSatU,
1745 0x94 => Operator::F64x2Nearest,
1746 0x95 => Operator::I16x8Mul,
1747 0x96 => Operator::I16x8MinS,
1748 0x97 => Operator::I16x8MinU,
1749 0x98 => Operator::I16x8MaxS,
1750 0x99 => Operator::I16x8MaxU,
1751 0x9b => Operator::I16x8RoundingAverageU,
1752 0x9c => Operator::I16x8ExtMulLowI8x16S,
1753 0x9d => Operator::I16x8ExtMulHighI8x16S,
1754 0x9e => Operator::I16x8ExtMulLowI8x16U,
1755 0x9f => Operator::I16x8ExtMulHighI8x16U,
1756 0xa0 => Operator::I32x4Abs,
1757 0xa1 => Operator::I32x4Neg,
1758 0xa3 => Operator::I32x4AllTrue,
1759 0xa4 => Operator::I32x4Bitmask,
1760 0xa7 => Operator::I32x4ExtendLowI16x8S,
1761 0xa8 => Operator::I32x4ExtendHighI16x8S,
1762 0xa9 => Operator::I32x4ExtendLowI16x8U,
1763 0xaa => Operator::I32x4ExtendHighI16x8U,
1764 0xab => Operator::I32x4Shl,
1765 0xac => Operator::I32x4ShrS,
1766 0xad => Operator::I32x4ShrU,
1767 0xae => Operator::I32x4Add,
1768 0xb1 => Operator::I32x4Sub,
1769 0xb5 => Operator::I32x4Mul,
1770 0xb6 => Operator::I32x4MinS,
1771 0xb7 => Operator::I32x4MinU,
1772 0xb8 => Operator::I32x4MaxS,
1773 0xb9 => Operator::I32x4MaxU,
1774 0xba => Operator::I32x4DotI16x8S,
1775 0xbc => Operator::I32x4ExtMulLowI16x8S,
1776 0xbd => Operator::I32x4ExtMulHighI16x8S,
1777 0xbe => Operator::I32x4ExtMulLowI16x8U,
1778 0xbf => Operator::I32x4ExtMulHighI16x8U,
1779 0xc0 => Operator::I64x2Abs,
1780 0xc1 => Operator::I64x2Neg,
1781 0xc3 => Operator::I64x2AllTrue,
1782 0xc4 => Operator::I64x2Bitmask,
1783 0xc7 => Operator::I64x2ExtendLowI32x4S,
1784 0xc8 => Operator::I64x2ExtendHighI32x4S,
1785 0xc9 => Operator::I64x2ExtendLowI32x4U,
1786 0xca => Operator::I64x2ExtendHighI32x4U,
1787 0xcb => Operator::I64x2Shl,
1788 0xcc => Operator::I64x2ShrS,
1789 0xcd => Operator::I64x2ShrU,
1790 0xce => Operator::I64x2Add,
1791 0xd1 => Operator::I64x2Sub,
1792 0xd5 => Operator::I64x2Mul,
1793 0xd6 => Operator::I64x2Eq,
1794 0xd7 => Operator::I64x2Ne,
1795 0xd8 => Operator::I64x2LtS,
1796 0xd9 => Operator::I64x2GtS,
1797 0xda => Operator::I64x2LeS,
1798 0xdb => Operator::I64x2GeS,
1799 0xdc => Operator::I64x2ExtMulLowI32x4S,
1800 0xdd => Operator::I64x2ExtMulHighI32x4S,
1801 0xde => Operator::I64x2ExtMulLowI32x4U,
1802 0xdf => Operator::I64x2ExtMulHighI32x4U,
1803 0xe0 => Operator::F32x4Abs,
1804 0xe1 => Operator::F32x4Neg,
1805 0xe3 => Operator::F32x4Sqrt,
1806 0xe4 => Operator::F32x4Add,
1807 0xe5 => Operator::F32x4Sub,
1808 0xe6 => Operator::F32x4Mul,
1809 0xe7 => Operator::F32x4Div,
1810 0xe8 => Operator::F32x4Min,
1811 0xe9 => Operator::F32x4Max,
1812 0xea => Operator::F32x4PMin,
1813 0xeb => Operator::F32x4PMax,
1814 0xec => Operator::F64x2Abs,
1815 0xed => Operator::F64x2Neg,
1816 0xef => Operator::F64x2Sqrt,
1817 0xf0 => Operator::F64x2Add,
1818 0xf1 => Operator::F64x2Sub,
1819 0xf2 => Operator::F64x2Mul,
1820 0xf3 => Operator::F64x2Div,
1821 0xf4 => Operator::F64x2Min,
1822 0xf5 => Operator::F64x2Max,
1823 0xf6 => Operator::F64x2PMin,
1824 0xf7 => Operator::F64x2PMax,
1825 0xf8 => Operator::I32x4TruncSatF32x4S,
1826 0xf9 => Operator::I32x4TruncSatF32x4U,
1827 0xfa => Operator::F32x4ConvertI32x4S,
1828 0xfb => Operator::F32x4ConvertI32x4U,
1829 0xfc => Operator::I32x4TruncSatF64x2SZero,
1830 0xfd => Operator::I32x4TruncSatF64x2UZero,
1831 0xfe => Operator::F64x2ConvertLowI32x4S,
1832 0xff => Operator::F64x2ConvertLowI32x4U,
1833
1834 _ => {
1835 return Err(BinaryReaderError::new(
1836 format!("Unknown 0xfd subopcode: 0x{:x}", code),
1837 self.original_position() - 1,
1838 ));
1839 }
1840 })
1841 }
1842
read_file_header(&mut self) -> Result<u32>1843 pub(crate) fn read_file_header(&mut self) -> Result<u32> {
1844 let magic_number = self.read_bytes(4)?;
1845 if magic_number != WASM_MAGIC_NUMBER {
1846 return Err(BinaryReaderError::new(
1847 "Bad magic number",
1848 self.original_position() - 4,
1849 ));
1850 }
1851 let version = self.read_u32()?;
1852 if version != WASM_SUPPORTED_VERSION && version != WASM_EXPERIMENTAL_VERSION {
1853 return Err(BinaryReaderError::new(
1854 "Bad version number",
1855 self.original_position() - 4,
1856 ));
1857 }
1858 Ok(version)
1859 }
1860
read_name_type(&mut self) -> Result<NameType>1861 pub(crate) fn read_name_type(&mut self) -> Result<NameType> {
1862 let code = self.read_var_u7()?;
1863 match code {
1864 0 => Ok(NameType::Module),
1865 1 => Ok(NameType::Function),
1866 2 => Ok(NameType::Local),
1867 _ => Ok(NameType::Unknown(code)),
1868 }
1869 }
1870
read_linking_type(&mut self) -> Result<LinkingType>1871 pub(crate) fn read_linking_type(&mut self) -> Result<LinkingType> {
1872 let ty = self.read_var_u32()?;
1873 Ok(match ty {
1874 1 => LinkingType::StackPointer(self.read_var_u32()?),
1875 _ => {
1876 return Err(BinaryReaderError::new(
1877 "Invalid linking type",
1878 self.original_position() - 1,
1879 ));
1880 }
1881 })
1882 }
1883
read_reloc_type(&mut self) -> Result<RelocType>1884 pub(crate) fn read_reloc_type(&mut self) -> Result<RelocType> {
1885 let code = self.read_var_u7()?;
1886 match code {
1887 0 => Ok(RelocType::FunctionIndexLEB),
1888 1 => Ok(RelocType::TableIndexSLEB),
1889 2 => Ok(RelocType::TableIndexI32),
1890 3 => Ok(RelocType::GlobalAddrLEB),
1891 4 => Ok(RelocType::GlobalAddrSLEB),
1892 5 => Ok(RelocType::GlobalAddrI32),
1893 6 => Ok(RelocType::TypeIndexLEB),
1894 7 => Ok(RelocType::GlobalIndexLEB),
1895 _ => Err(BinaryReaderError::new(
1896 "Invalid reloc type",
1897 self.original_position() - 1,
1898 )),
1899 }
1900 }
1901
skip_init_expr(&mut self) -> Result<()>1902 pub(crate) fn skip_init_expr(&mut self) -> Result<()> {
1903 // TODO add skip_operator() method and/or validate init_expr operators.
1904 loop {
1905 if let Operator::End = self.read_operator()? {
1906 return Ok(());
1907 }
1908 }
1909 }
1910 }
1911
1912 impl<'a> BrTable<'a> {
1913 /// Returns the number of `br_table` entries, not including the default
1914 /// label
len(&self) -> usize1915 pub fn len(&self) -> usize {
1916 self.cnt
1917 }
1918
1919 /// Returns whether `BrTable` doesn't have any labels apart from the default one.
is_empty(&self) -> bool1920 pub fn is_empty(&self) -> bool {
1921 self.len() == 0
1922 }
1923
1924 /// Returns the list of targets that this `br_table` instruction will be
1925 /// jumping to.
1926 ///
1927 /// This method will return an iterator which parses each target of this
1928 /// `br_table` as well as the default target. The returned iterator will
1929 /// yield `self.len() + 1` elements.
1930 ///
1931 /// Each iterator item is a tuple of `(u32, bool)`, where the first item is
1932 /// the relative depth of the jump and the second item is `true` if the item
1933 /// is the default label. You're guaranteed that `true` will only show up
1934 /// for the final element of the iterator.
1935 ///
1936 /// #Examples
1937 ///
1938 /// ```rust
1939 /// let buf = [0x0e, 0x02, 0x01, 0x02, 0x00];
1940 /// let mut reader = wasmparser::BinaryReader::new(&buf);
1941 /// let op = reader.read_operator().unwrap();
1942 /// if let wasmparser::Operator::BrTable { table } = op {
1943 /// let targets = table.targets().collect::<Result<Vec<_>, _>>().unwrap();
1944 /// assert_eq!(targets, [(1, false), (2, false), (0, true)]);
1945 /// }
1946 /// ```
targets<'b>(&'b self) -> impl Iterator<Item = Result<(u32, bool)>> + 'b1947 pub fn targets<'b>(&'b self) -> impl Iterator<Item = Result<(u32, bool)>> + 'b {
1948 let mut reader = self.reader.clone();
1949 (0..self.cnt + 1).map(move |i| {
1950 let label = reader.read_var_u32()?;
1951 let ret = (label, i == self.cnt);
1952 if ret.1 && !reader.eof() {
1953 return Err(BinaryReaderError::new(
1954 "trailing data in br_table",
1955 reader.original_position(),
1956 ));
1957 }
1958 Ok(ret)
1959 })
1960 }
1961 }
1962
1963 impl fmt::Debug for BrTable<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1964 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1965 let mut f = f.debug_struct("BrTable");
1966 f.field("count", &self.cnt);
1967 match self.targets().collect::<Result<Vec<_>>>() {
1968 Ok(targets) => {
1969 f.field("targets", &targets);
1970 }
1971 Err(_) => {
1972 f.field("reader", &self.reader);
1973 }
1974 }
1975 f.finish()
1976 }
1977 }
1978