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
16use crate::prelude::*;
17use crate::{limits::*, *};
18use core::fmt;
19use core::marker;
20use core::ops::Range;
21use core::str;
22
23pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
24
25/// A binary reader for WebAssembly modules.
26#[derive(Debug, Clone)]
27pub struct BinaryReaderError {
28 // Wrap the actual error data in a `Box` so that the error is just one
29 // word. This means that we can continue returning small `Result`s in
30 // registers.
31 pub(crate) inner: Box<BinaryReaderErrorInner>,
32}
33
34#[derive(Debug, Clone)]
35pub(crate) struct BinaryReaderErrorInner {
36 pub(crate) message: String,
37 pub(crate) kind: BinaryReaderErrorKind,
38 pub(crate) offset: usize,
39 pub(crate) needed_hint: Option<usize>,
40}
41
42#[derive(Debug, Clone, Copy)]
43pub(crate) enum BinaryReaderErrorKind {
44 Custom,
45 Invalid,
46}
47
48/// The result for `BinaryReader` operations.
49pub type Result<T, E = BinaryReaderError> = core::result::Result<T, E>;
50
51#[cfg(feature = "std")]
52impl std::error::Error for BinaryReaderError {}
53
54impl fmt::Display for BinaryReaderError {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 write!(
57 f,
58 "{} (at offset 0x{:x})",
59 self.inner.message, self.inner.offset
60 )
61 }
62}
63
64impl BinaryReaderError {
65 #[cold]
66 pub(crate) fn _new(kind: BinaryReaderErrorKind, message: String, offset: usize) -> Self {
67 BinaryReaderError {
68 inner: Box::new(BinaryReaderErrorInner {
69 kind,
70 message,
71 offset,
72 needed_hint: None,
73 }),
74 }
75 }
76
77 #[cold]
78 pub(crate) fn new(message: impl Into<String>, offset: usize) -> Self {
79 Self::_new(BinaryReaderErrorKind::Custom, message.into(), offset)
80 }
81
82 #[cold]
83 pub(crate) fn invalid(msg: &'static str, offset: usize) -> Self {
84 Self::_new(BinaryReaderErrorKind::Invalid, msg.into(), offset)
85 }
86
87 #[cold]
88 pub(crate) fn fmt(args: fmt::Arguments<'_>, offset: usize) -> Self {
89 BinaryReaderError::new(args.to_string(), offset)
90 }
91
92 #[cold]
93 pub(crate) fn eof(offset: usize, needed_hint: usize) -> Self {
94 let mut err = BinaryReaderError::new("unexpected end-of-file", offset);
95 err.inner.needed_hint = Some(needed_hint);
96 err
97 }
98
99 pub(crate) fn kind(&mut self) -> BinaryReaderErrorKind {
100 self.inner.kind
101 }
102
103 /// Get this error's message.
104 pub fn message(&self) -> &str {
105 &self.inner.message
106 }
107
108 /// Get the offset within the Wasm binary where the error occurred.
109 pub fn offset(&self) -> usize {
110 self.inner.offset
111 }
112
113 #[cfg(all(feature = "validate", feature = "component-model"))]
114 pub(crate) fn add_context(&mut self, context: String) {
115 self.inner.message = format!("{context}\n{}", self.inner.message);
116 }
117
118 pub(crate) fn set_message(&mut self, message: &str) {
119 self.inner.message = message.to_string();
120 }
121}
122
123/// A binary reader of the WebAssembly structures and types.
124#[derive(Clone, Debug, Hash)]
125pub struct BinaryReader<'a> {
126 buffer: &'a [u8],
127 position: usize,
128 original_offset: usize,
129
130 // When the `features` feature is disabled then the `WasmFeatures` type
131 // still exists but this field is still omitted. When `features` is
132 // disabled then the only constructor of this type is `BinaryReader::new`
133 // which documents all known features being active. All known features
134 // being active isn't represented by `WasmFeatures` when the feature is
135 // disabled so the field is omitted here to prevent accidentally using the
136 // wrong listing of features.
137 //
138 // Feature accessors are defined by `foreach_wasm_feature!` below with a
139 // method-per-feature on `BinaryReader` which when the `features` feature
140 // is disabled returns `true` by default.
141 #[cfg(feature = "features")]
142 features: WasmFeatures,
143}
144
145impl<'a> BinaryReader<'a> {
146 /// Creates a new binary reader which will parse the `data` provided.
147 ///
148 /// The `original_offset` provided is used for byte offsets in errors that
149 /// are generated. That offset is added to the current position in `data`.
150 /// This can be helpful when `data` is just a window of a view into a larger
151 /// wasm binary perhaps not even entirely stored locally.
152 ///
153 /// The returned binary reader will have all features known to this crate
154 /// enabled. To reject binaries that aren't valid unless a certain feature
155 /// is enabled use the [`BinaryReader::new_features`] constructor instead.
156 pub fn new(data: &[u8], original_offset: usize) -> BinaryReader {
157 BinaryReader {
158 buffer: data,
159 position: 0,
160 original_offset,
161 #[cfg(feature = "features")]
162 features: WasmFeatures::all(),
163 }
164 }
165
166 /// Creates a new binary reader which will parse the `data` provided.
167 ///
168 /// The `original_offset` provided is used for byte offsets in errors that
169 /// are generated. That offset is added to the current position in `data`.
170 /// This can be helpful when `data` is just a window of a view into a larger
171 /// wasm binary perhaps not even entirely stored locally.
172 ///
173 /// The `features` argument provided controls which WebAssembly features are
174 /// active when parsing this data. Wasm features typically don't affect
175 /// parsing too too much and are generally more applicable during
176 /// validation, but features and proposals will often reinterpret
177 /// previously-invalid constructs as now-valid things meaning something
178 /// slightly different. This means that invalid bytes before a feature may
179 /// now be interpreted differently after a feature is implemented. This
180 /// means that the set of activated features can affect what errors are
181 /// generated and when they are generated.
182 ///
183 /// In general it's safe to pass `WasmFeatures::all()` here. There's no
184 /// downside to enabling all features while parsing and only enabling a
185 /// subset of features during validation.
186 ///
187 /// Note that the activated set of features does not guarantee that
188 /// `BinaryReader` will return an error for disabled features. For example
189 /// if SIMD is disabled then SIMD instructions will still be parsed via
190 /// [`BinaryReader::visit_operator`]. Validation must still be performed to
191 /// provide a strict guarantee that if a feature is disabled that a binary
192 /// doesn't leverage the feature. The activated set of features here instead
193 /// only affects locations where preexisting bytes are reinterpreted in
194 /// different ways with future proposals, such as the `memarg` moving from a
195 /// 32-bit offset to a 64-bit offset with the `memory64` proposal.
196 #[cfg(feature = "features")]
197 pub fn new_features(
198 data: &[u8],
199 original_offset: usize,
200 features: WasmFeatures,
201 ) -> BinaryReader {
202 BinaryReader {
203 buffer: data,
204 position: 0,
205 original_offset,
206 features,
207 }
208 }
209
210 /// "Shrinks" this binary reader to retain only the buffer left-to-parse.
211 ///
212 /// The primary purpose of this method is to change the return value of the
213 /// `range()` method. That method returns the range of the original buffer
214 /// within the wasm binary so calling `range()` on the returned
215 /// `BinaryReader` will return a smaller range than if `range()` is called
216 /// on `self`.
217 ///
218 /// Otherwise parsing values from either `self` or the return value should
219 /// return the same thing.
220 pub(crate) fn shrink(&self) -> BinaryReader<'a> {
221 BinaryReader {
222 buffer: &self.buffer[self.position..],
223 position: 0,
224 original_offset: self.original_offset + self.position,
225 #[cfg(feature = "features")]
226 features: self.features,
227 }
228 }
229
230 /// Gets the original position of the binary reader.
231 #[inline]
232 pub fn original_position(&self) -> usize {
233 self.original_offset + self.position
234 }
235
236 /// Returns the currently active set of wasm features that this reader is
237 /// using while parsing.
238 ///
239 /// For more information see [`BinaryReader::new`].
240 #[cfg(feature = "features")]
241 pub fn features(&self) -> WasmFeatures {
242 self.features
243 }
244
245 /// Sets the wasm features active while parsing to the `features` specified.
246 ///
247 /// For more information see [`BinaryReader::new`].
248 #[cfg(feature = "features")]
249 pub fn set_features(&mut self, features: WasmFeatures) {
250 self.features = features;
251 }
252
253 /// Returns a range from the starting offset to the end of the buffer.
254 pub fn range(&self) -> Range<usize> {
255 self.original_offset..self.original_offset + self.buffer.len()
256 }
257
258 pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
259 &self.buffer[self.position..]
260 }
261
262 fn ensure_has_byte(&self) -> Result<()> {
263 if self.position < self.buffer.len() {
264 Ok(())
265 } else {
266 Err(BinaryReaderError::eof(self.original_position(), 1))
267 }
268 }
269
270 pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
271 if self.position + len <= self.buffer.len() {
272 Ok(())
273 } else {
274 let hint = self.position + len - self.buffer.len();
275 Err(BinaryReaderError::eof(self.original_position(), hint))
276 }
277 }
278
279 /// Reads a value of type `T` from this binary reader, advancing the
280 /// internal position in this reader forward as data is read.
281 #[inline]
282 pub fn read<T>(&mut self) -> Result<T>
283 where
284 T: FromReader<'a>,
285 {
286 T::from_reader(self)
287 }
288
289 pub(crate) fn read_u7(&mut self) -> Result<u8> {
290 let b = self.read_u8()?;
291 if (b & 0x80) != 0 {
292 return Err(BinaryReaderError::new(
293 "invalid u7",
294 self.original_position() - 1,
295 ));
296 }
297 Ok(b)
298 }
299
300 pub(crate) fn external_kind_from_byte(byte: u8, offset: usize) -> Result<ExternalKind> {
301 match byte {
302 0x00 => Ok(ExternalKind::Func),
303 0x01 => Ok(ExternalKind::Table),
304 0x02 => Ok(ExternalKind::Memory),
305 0x03 => Ok(ExternalKind::Global),
306 0x04 => Ok(ExternalKind::Tag),
307 x => Err(Self::invalid_leading_byte_error(x, "external kind", offset)),
308 }
309 }
310
311 /// Reads a variable-length 32-bit size from the byte stream while checking
312 /// against a limit.
313 pub fn read_size(&mut self, limit: usize, desc: &str) -> Result<usize> {
314 let pos = self.original_position();
315 let size = self.read_var_u32()? as usize;
316 if size > limit {
317 bail!(pos, "{desc} size is out of bounds");
318 }
319 Ok(size)
320 }
321
322 /// Reads a variable-length 32-bit size from the byte stream while checking
323 /// against a limit.
324 ///
325 /// Then reads that many values of type `T` and returns them as an iterator.
326 ///
327 /// Note that regardless of how many items are read from the returned
328 /// iterator the items will still be parsed from this reader.
329 pub fn read_iter<'me, T>(
330 &'me mut self,
331 limit: usize,
332 desc: &str,
333 ) -> Result<BinaryReaderIter<'a, 'me, T>>
334 where
335 T: FromReader<'a>,
336 {
337 let size = self.read_size(limit, desc)?;
338 Ok(BinaryReaderIter {
339 remaining: size,
340 reader: self,
341 _marker: marker::PhantomData,
342 })
343 }
344
345 fn read_memarg(&mut self, max_align: u8) -> Result<MemArg> {
346 let flags_pos = self.original_position();
347 let mut flags = self.read_var_u32()?;
348
349 let memory = if self.multi_memory() && flags & (1 << 6) != 0 {
350 flags ^= 1 << 6;
351 self.read_var_u32()?
352 } else {
353 0
354 };
355 let align = if flags >= (1 << 6) {
356 return Err(BinaryReaderError::new(
357 "malformed memop alignment: alignment too large",
358 flags_pos,
359 ));
360 } else {
361 flags as u8
362 };
363 let offset = if self.memory64() {
364 self.read_var_u64()?
365 } else {
366 u64::from(self.read_var_u32()?)
367 };
368 Ok(MemArg {
369 align,
370 max_align,
371 offset,
372 memory,
373 })
374 }
375
376 fn read_ordering(&mut self) -> Result<Ordering> {
377 let byte = self.read_var_u32()?;
378 match byte {
379 0 => Ok(Ordering::SeqCst),
380 1 => Ok(Ordering::AcqRel),
381 x => Err(BinaryReaderError::new(
382 &format!("invalid atomic consistency ordering {}", x),
383 self.original_position() - 1,
384 )),
385 }
386 }
387
388 fn read_br_table(&mut self) -> Result<BrTable<'a>> {
389 let cnt = self.read_size(MAX_WASM_BR_TABLE_SIZE, "br_table")?;
390 let reader = self.skip(|reader| {
391 for _ in 0..cnt {
392 reader.read_var_u32()?;
393 }
394 Ok(())
395 })?;
396 let default = self.read_var_u32()?;
397 Ok(BrTable {
398 reader,
399 cnt: cnt as u32,
400 default,
401 })
402 }
403
404 /// Returns whether the `BinaryReader` has reached the end of the file.
405 #[inline]
406 pub fn eof(&self) -> bool {
407 self.position >= self.buffer.len()
408 }
409
410 /// Returns the `BinaryReader`'s current position.
411 #[inline]
412 pub fn current_position(&self) -> usize {
413 self.position
414 }
415
416 /// Returns the number of bytes remaining in the `BinaryReader`.
417 #[inline]
418 pub fn bytes_remaining(&self) -> usize {
419 self.buffer.len() - self.position
420 }
421
422 /// Advances the `BinaryReader` `size` bytes, and returns a slice from the
423 /// current position of `size` length.
424 ///
425 /// # Errors
426 /// If `size` exceeds the remaining length in `BinaryReader`.
427 pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
428 self.ensure_has_bytes(size)?;
429 let start = self.position;
430 self.position += size;
431 Ok(&self.buffer[start..self.position])
432 }
433
434 /// Reads a length-prefixed list of bytes from this reader and returns a
435 /// new `BinaryReader` to read that list of bytes.
436 pub fn read_reader(&mut self) -> Result<BinaryReader<'a>> {
437 let size = self.read_var_u32()? as usize;
438 self.skip(|reader| {
439 reader.read_bytes(size)?;
440 Ok(())
441 })
442 }
443
444 /// Advances the `BinaryReader` four bytes and returns a `u32`.
445 /// # Errors
446 /// If `BinaryReader` has less than four bytes remaining.
447 pub fn read_u32(&mut self) -> Result<u32> {
448 self.ensure_has_bytes(4)?;
449 let word = u32::from_le_bytes(
450 self.buffer[self.position..self.position + 4]
451 .try_into()
452 .unwrap(),
453 );
454 self.position += 4;
455 Ok(word)
456 }
457
458 /// Advances the `BinaryReader` eight bytes and returns a `u64`.
459 /// # Errors
460 /// If `BinaryReader` has less than eight bytes remaining.
461 pub fn read_u64(&mut self) -> Result<u64> {
462 self.ensure_has_bytes(8)?;
463 let word = u64::from_le_bytes(
464 self.buffer[self.position..self.position + 8]
465 .try_into()
466 .unwrap(),
467 );
468 self.position += 8;
469 Ok(word)
470 }
471
472 /// Advances the `BinaryReader` a single byte.
473 ///
474 /// # Errors
475 ///
476 /// If `BinaryReader` has no bytes remaining.
477 #[inline]
478 pub fn read_u8(&mut self) -> Result<u8> {
479 let b = match self.buffer.get(self.position) {
480 Some(b) => *b,
481 None => return Err(self.eof_err()),
482 };
483 self.position += 1;
484 Ok(b)
485 }
486
487 #[cold]
488 fn eof_err(&self) -> BinaryReaderError {
489 BinaryReaderError::eof(self.original_position(), 1)
490 }
491
492 /// Advances the `BinaryReader` up to four bytes to parse a variable
493 /// length integer as a `u32`.
494 ///
495 /// # Errors
496 ///
497 /// If `BinaryReader` has less than one or up to four bytes remaining, or
498 /// the integer is larger than 32 bits.
499 #[inline]
500 pub fn read_var_u32(&mut self) -> Result<u32> {
501 // Optimization for single byte i32.
502 let byte = self.read_u8()?;
503 if (byte & 0x80) == 0 {
504 Ok(u32::from(byte))
505 } else {
506 self.read_var_u32_big(byte)
507 }
508 }
509
510 fn read_var_u32_big(&mut self, byte: u8) -> Result<u32> {
511 let mut result = (byte & 0x7F) as u32;
512 let mut shift = 7;
513 loop {
514 let byte = self.read_u8()?;
515 result |= ((byte & 0x7F) as u32) << shift;
516 if shift >= 25 && (byte >> (32 - shift)) != 0 {
517 let msg = if byte & 0x80 != 0 {
518 "invalid var_u32: integer representation too long"
519 } else {
520 "invalid var_u32: integer too large"
521 };
522 // The continuation bit or unused bits are set.
523 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
524 }
525 shift += 7;
526 if (byte & 0x80) == 0 {
527 break;
528 }
529 }
530 Ok(result)
531 }
532
533 /// Advances the `BinaryReader` up to four bytes to parse a variable
534 /// length integer as a `u64`.
535 ///
536 /// # Errors
537 ///
538 /// If `BinaryReader` has less than one or up to eight bytes remaining, or
539 /// the integer is larger than 64 bits.
540 #[inline]
541 pub fn read_var_u64(&mut self) -> Result<u64> {
542 // Optimization for single byte u64.
543 let byte = u64::from(self.read_u8()?);
544 if (byte & 0x80) == 0 {
545 Ok(byte)
546 } else {
547 self.read_var_u64_big(byte)
548 }
549 }
550
551 fn read_var_u64_big(&mut self, byte: u64) -> Result<u64> {
552 let mut result = byte & 0x7F;
553 let mut shift = 7;
554 loop {
555 let byte = u64::from(self.read_u8()?);
556 result |= (byte & 0x7F) << shift;
557 if shift >= 57 && (byte >> (64 - shift)) != 0 {
558 let msg = if byte & 0x80 != 0 {
559 "invalid var_u64: integer representation too long"
560 } else {
561 "invalid var_u64: integer too large"
562 };
563 // The continuation bit or unused bits are set.
564 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
565 }
566 shift += 7;
567 if (byte & 0x80) == 0 {
568 break;
569 }
570 }
571 Ok(result)
572 }
573
574 /// Executes `f` to skip some data in this binary reader and then returns a
575 /// reader which will read the skipped data.
576 pub fn skip(&mut self, f: impl FnOnce(&mut Self) -> Result<()>) -> Result<Self> {
577 let start = self.position;
578 f(self)?;
579 let mut ret = self.clone();
580 ret.buffer = &self.buffer[start..self.position];
581 ret.position = 0;
582 ret.original_offset = self.original_offset + start;
583 Ok(ret)
584 }
585
586 /// Advances the `BinaryReader` past a WebAssembly string. This method does
587 /// not perform any utf-8 validation.
588 /// # Errors
589 /// If `BinaryReader` has less than four bytes, the string's length exceeds
590 /// the remaining bytes, or the string length
591 /// exceeds `limits::MAX_WASM_STRING_SIZE`.
592 pub fn skip_string(&mut self) -> Result<()> {
593 let len = self.read_var_u32()? as usize;
594 if len > MAX_WASM_STRING_SIZE {
595 return Err(BinaryReaderError::new(
596 "string size out of bounds",
597 self.original_position() - 1,
598 ));
599 }
600 self.ensure_has_bytes(len)?;
601 self.position += len;
602 Ok(())
603 }
604
605 /// Advances the `BinaryReader` up to four bytes to parse a variable
606 /// length integer as a `i32`.
607 /// # Errors
608 /// If `BinaryReader` has less than one or up to four bytes remaining, or
609 /// the integer is larger than 32 bits.
610 #[inline]
611 pub fn read_var_i32(&mut self) -> Result<i32> {
612 // Optimization for single byte i32.
613 let byte = self.read_u8()?;
614 if (byte & 0x80) == 0 {
615 Ok(((byte as i32) << 25) >> 25)
616 } else {
617 self.read_var_i32_big(byte)
618 }
619 }
620
621 fn read_var_i32_big(&mut self, byte: u8) -> Result<i32> {
622 let mut result = (byte & 0x7F) as i32;
623 let mut shift = 7;
624 loop {
625 let byte = self.read_u8()?;
626 result |= ((byte & 0x7F) as i32) << shift;
627 if shift >= 25 {
628 let continuation_bit = (byte & 0x80) != 0;
629 let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
630 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
631 let msg = if continuation_bit {
632 "invalid var_i32: integer representation too long"
633 } else {
634 "invalid var_i32: integer too large"
635 };
636 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
637 }
638 return Ok(result);
639 }
640 shift += 7;
641 if (byte & 0x80) == 0 {
642 break;
643 }
644 }
645 let ashift = 32 - shift;
646 Ok((result << ashift) >> ashift)
647 }
648
649 /// Advances the `BinaryReader` up to four bytes to parse a variable
650 /// length integer as a signed 33 bit integer, returned as a `i64`.
651 /// # Errors
652 /// If `BinaryReader` has less than one or up to five bytes remaining, or
653 /// the integer is larger than 33 bits.
654 pub fn read_var_s33(&mut self) -> Result<i64> {
655 // Optimization for single byte.
656 let byte = self.read_u8()?;
657 if (byte & 0x80) == 0 {
658 return Ok(((byte as i8) << 1) as i64 >> 1);
659 }
660
661 let mut result = (byte & 0x7F) as i64;
662 let mut shift = 7;
663 loop {
664 let byte = self.read_u8()?;
665 result |= ((byte & 0x7F) as i64) << shift;
666 if shift >= 25 {
667 let continuation_bit = (byte & 0x80) != 0;
668 let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
669 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
670 return Err(BinaryReaderError::new(
671 "invalid var_s33: integer representation too long",
672 self.original_position() - 1,
673 ));
674 }
675 return Ok(result);
676 }
677 shift += 7;
678 if (byte & 0x80) == 0 {
679 break;
680 }
681 }
682 let ashift = 64 - shift;
683 Ok((result << ashift) >> ashift)
684 }
685
686 /// Advances the `BinaryReader` up to eight bytes to parse a variable
687 /// length integer as a 64 bit integer, returned as a `i64`.
688 /// # Errors
689 /// If `BinaryReader` has less than one or up to eight bytes remaining, or
690 /// the integer is larger than 64 bits.
691 pub fn read_var_i64(&mut self) -> Result<i64> {
692 let mut result: i64 = 0;
693 let mut shift = 0;
694 loop {
695 let byte = self.read_u8()?;
696 result |= i64::from(byte & 0x7F) << shift;
697 if shift >= 57 {
698 let continuation_bit = (byte & 0x80) != 0;
699 let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
700 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
701 let msg = if continuation_bit {
702 "invalid var_i64: integer representation too long"
703 } else {
704 "invalid var_i64: integer too large"
705 };
706 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
707 }
708 return Ok(result);
709 }
710 shift += 7;
711 if (byte & 0x80) == 0 {
712 break;
713 }
714 }
715 let ashift = 64 - shift;
716 Ok((result << ashift) >> ashift)
717 }
718
719 /// Advances the `BinaryReader` four bytes to parse a 32 bit floating point
720 /// number, returned as `Ieee32`.
721 /// # Errors
722 /// If `BinaryReader` has less than four bytes remaining.
723 pub fn read_f32(&mut self) -> Result<Ieee32> {
724 let value = self.read_u32()?;
725 Ok(Ieee32(value))
726 }
727
728 /// Advances the `BinaryReader` eight bytes to parse a 64 bit floating point
729 /// number, returned as `Ieee64`.
730 /// # Errors
731 /// If `BinaryReader` has less than eight bytes remaining.
732 pub fn read_f64(&mut self) -> Result<Ieee64> {
733 let value = self.read_u64()?;
734 Ok(Ieee64(value))
735 }
736
737 /// (internal) Reads a fixed-size WebAssembly string from the module.
738 fn internal_read_string(&mut self, len: usize) -> Result<&'a str> {
739 let bytes = self.read_bytes(len)?;
740 str::from_utf8(bytes).map_err(|_| {
741 BinaryReaderError::new("malformed UTF-8 encoding", self.original_position() - 1)
742 })
743 }
744
745 /// Reads a WebAssembly string from the module.
746 ///
747 /// # Errors
748 ///
749 /// If `BinaryReader` has less than up to four bytes remaining, the string's
750 /// length exceeds the remaining bytes, the string's length exceeds
751 /// `limits::MAX_WASM_STRING_SIZE`, or the string contains invalid utf-8.
752 pub fn read_string(&mut self) -> Result<&'a str> {
753 let len = self.read_var_u32()? as usize;
754 if len > MAX_WASM_STRING_SIZE {
755 return Err(BinaryReaderError::new(
756 "string size out of bounds",
757 self.original_position() - 1,
758 ));
759 }
760 return self.internal_read_string(len);
761 }
762
763 /// Reads a unlimited WebAssembly string from the module.
764 ///
765 /// Note that this is similar to [`BinaryReader::read_string`] except that
766 /// it will not limit the size of the returned string by
767 /// `limits::MAX_WASM_STRING_SIZE`.
768 pub fn read_unlimited_string(&mut self) -> Result<&'a str> {
769 let len = self.read_var_u32()? as usize;
770 return self.internal_read_string(len);
771 }
772
773 #[cold]
774 pub(crate) fn invalid_leading_byte<T>(&self, byte: u8, desc: &str) -> Result<T> {
775 Err(Self::invalid_leading_byte_error(
776 byte,
777 desc,
778 self.original_position() - 1,
779 ))
780 }
781
782 pub(crate) fn invalid_leading_byte_error(
783 byte: u8,
784 desc: &str,
785 offset: usize,
786 ) -> BinaryReaderError {
787 format_err!(offset, "invalid leading byte (0x{byte:x}) for {desc}")
788 }
789
790 pub(crate) fn peek(&self) -> Result<u8> {
791 self.ensure_has_byte()?;
792 Ok(self.buffer[self.position])
793 }
794
795 pub(crate) fn read_block_type(&mut self) -> Result<BlockType> {
796 let b = self.peek()?;
797
798 // Block types are encoded as either 0x40, a `valtype`, or `s33`. All
799 // current `valtype` encodings are negative numbers when encoded with
800 // sleb128, but it's also required that valtype encodings are in their
801 // canonical form. For example an overlong encoding of -1 as `0xff 0x7f`
802 // is not valid and it is required to be `0x7f`. This means that we
803 // can't simply match on the `s33` that pops out below since reading the
804 // whole `s33` might read an overlong encoding.
805 //
806 // To test for this the first byte `b` is inspected. The highest bit,
807 // the continuation bit in LEB128 encoding, must be clear. The next bit,
808 // the sign bit, must be set to indicate that the number is negative. If
809 // these two conditions hold then we're guaranteed that this is a
810 // negative number.
811 //
812 // After this a value type is read directly instead of looking for an
813 // indexed value type.
814 if b & 0x80 == 0 && b & 0x40 != 0 {
815 if b == 0x40 {
816 self.position += 1;
817 return Ok(BlockType::Empty);
818 }
819 return Ok(BlockType::Type(self.read()?));
820 }
821
822 // Not empty or a singular type, so read the function type index
823 let idx = self.read_var_s33()?;
824 match u32::try_from(idx) {
825 Ok(idx) => Ok(BlockType::FuncType(idx)),
826 Err(_) => {
827 return Err(BinaryReaderError::new(
828 "invalid function type",
829 self.original_position(),
830 ));
831 }
832 }
833 }
834
835 /// Visit the next available operator with the specified [`VisitOperator`] instance.
836 ///
837 /// Note that this does not implicitly propagate any additional information such as instruction
838 /// offsets. In order to do so, consider storing such data within the visitor before visiting.
839 ///
840 /// # Errors
841 ///
842 /// If `BinaryReader` has less bytes remaining than required to parse the `Operator`.
843 ///
844 /// # Examples
845 ///
846 /// Store an offset for use in diagnostics or any other purposes:
847 ///
848 /// ```
849 /// # use wasmparser::{BinaryReader, VisitOperator, Result, for_each_operator};
850 ///
851 /// pub fn dump(mut reader: BinaryReader) -> Result<()> {
852 /// let mut visitor = Dumper { offset: 0 };
853 /// while !reader.eof() {
854 /// visitor.offset = reader.original_position();
855 /// reader.visit_operator(&mut visitor)?;
856 /// }
857 /// Ok(())
858 /// }
859 ///
860 /// struct Dumper {
861 /// offset: usize
862 /// }
863 ///
864 /// macro_rules! define_visit_operator {
865 /// ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
866 /// $(
867 /// fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
868 /// println!("{}: {}", self.offset, stringify!($visit));
869 /// }
870 /// )*
871 /// }
872 /// }
873 ///
874 /// impl<'a> VisitOperator<'a> for Dumper {
875 /// type Output = ();
876 /// for_each_operator!(define_visit_operator);
877 /// }
878 ///
879 /// ```
880 pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
881 where
882 T: VisitOperator<'a>,
883 {
884 let pos = self.original_position();
885 let code = self.read_u8()? as u8;
886 Ok(match code {
887 0x00 => visitor.visit_unreachable(),
888 0x01 => visitor.visit_nop(),
889 0x02 => visitor.visit_block(self.read_block_type()?),
890 0x03 => visitor.visit_loop(self.read_block_type()?),
891 0x04 => visitor.visit_if(self.read_block_type()?),
892 0x05 => visitor.visit_else(),
893 0x06 => visitor.visit_try(self.read_block_type()?),
894 0x07 => visitor.visit_catch(self.read_var_u32()?),
895 0x08 => visitor.visit_throw(self.read_var_u32()?),
896 0x09 => visitor.visit_rethrow(self.read_var_u32()?),
897 0x0a => visitor.visit_throw_ref(),
898 0x0b => visitor.visit_end(),
899 0x0c => visitor.visit_br(self.read_var_u32()?),
900 0x0d => visitor.visit_br_if(self.read_var_u32()?),
901 0x0e => visitor.visit_br_table(self.read_br_table()?),
902 0x0f => visitor.visit_return(),
903 0x10 => visitor.visit_call(self.read_var_u32()?),
904 0x11 => {
905 let index = self.read_var_u32()?;
906 let table = self.read_table_index_or_zero_if_not_reference_types()?;
907 visitor.visit_call_indirect(index, table)
908 }
909 0x12 => visitor.visit_return_call(self.read_var_u32()?),
910 0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?),
911 0x14 => visitor.visit_call_ref(self.read()?),
912 0x15 => visitor.visit_return_call_ref(self.read()?),
913 0x18 => visitor.visit_delegate(self.read_var_u32()?),
914 0x19 => visitor.visit_catch_all(),
915 0x1a => visitor.visit_drop(),
916 0x1b => visitor.visit_select(),
917 0x1c => {
918 let results = self.read_var_u32()?;
919 if results != 1 {
920 return Err(BinaryReaderError::new(
921 "invalid result arity",
922 self.position,
923 ));
924 }
925 visitor.visit_typed_select(self.read()?)
926 }
927 0x1f => visitor.visit_try_table(self.read()?),
928
929 0x20 => visitor.visit_local_get(self.read_var_u32()?),
930 0x21 => visitor.visit_local_set(self.read_var_u32()?),
931 0x22 => visitor.visit_local_tee(self.read_var_u32()?),
932 0x23 => visitor.visit_global_get(self.read_var_u32()?),
933 0x24 => visitor.visit_global_set(self.read_var_u32()?),
934 0x25 => visitor.visit_table_get(self.read_var_u32()?),
935 0x26 => visitor.visit_table_set(self.read_var_u32()?),
936
937 0x28 => visitor.visit_i32_load(self.read_memarg(2)?),
938 0x29 => visitor.visit_i64_load(self.read_memarg(3)?),
939 0x2a => visitor.visit_f32_load(self.read_memarg(2)?),
940 0x2b => visitor.visit_f64_load(self.read_memarg(3)?),
941 0x2c => visitor.visit_i32_load8_s(self.read_memarg(0)?),
942 0x2d => visitor.visit_i32_load8_u(self.read_memarg(0)?),
943 0x2e => visitor.visit_i32_load16_s(self.read_memarg(1)?),
944 0x2f => visitor.visit_i32_load16_u(self.read_memarg(1)?),
945 0x30 => visitor.visit_i64_load8_s(self.read_memarg(0)?),
946 0x31 => visitor.visit_i64_load8_u(self.read_memarg(0)?),
947 0x32 => visitor.visit_i64_load16_s(self.read_memarg(1)?),
948 0x33 => visitor.visit_i64_load16_u(self.read_memarg(1)?),
949 0x34 => visitor.visit_i64_load32_s(self.read_memarg(2)?),
950 0x35 => visitor.visit_i64_load32_u(self.read_memarg(2)?),
951 0x36 => visitor.visit_i32_store(self.read_memarg(2)?),
952 0x37 => visitor.visit_i64_store(self.read_memarg(3)?),
953 0x38 => visitor.visit_f32_store(self.read_memarg(2)?),
954 0x39 => visitor.visit_f64_store(self.read_memarg(3)?),
955 0x3a => visitor.visit_i32_store8(self.read_memarg(0)?),
956 0x3b => visitor.visit_i32_store16(self.read_memarg(1)?),
957 0x3c => visitor.visit_i64_store8(self.read_memarg(0)?),
958 0x3d => visitor.visit_i64_store16(self.read_memarg(1)?),
959 0x3e => visitor.visit_i64_store32(self.read_memarg(2)?),
960 0x3f => {
961 let mem = self.read_memory_index_or_zero_if_not_multi_memory()?;
962 visitor.visit_memory_size(mem)
963 }
964 0x40 => {
965 let mem = self.read_memory_index_or_zero_if_not_multi_memory()?;
966 visitor.visit_memory_grow(mem)
967 }
968
969 0x41 => visitor.visit_i32_const(self.read_var_i32()?),
970 0x42 => visitor.visit_i64_const(self.read_var_i64()?),
971 0x43 => visitor.visit_f32_const(self.read_f32()?),
972 0x44 => visitor.visit_f64_const(self.read_f64()?),
973
974 0x45 => visitor.visit_i32_eqz(),
975 0x46 => visitor.visit_i32_eq(),
976 0x47 => visitor.visit_i32_ne(),
977 0x48 => visitor.visit_i32_lt_s(),
978 0x49 => visitor.visit_i32_lt_u(),
979 0x4a => visitor.visit_i32_gt_s(),
980 0x4b => visitor.visit_i32_gt_u(),
981 0x4c => visitor.visit_i32_le_s(),
982 0x4d => visitor.visit_i32_le_u(),
983 0x4e => visitor.visit_i32_ge_s(),
984 0x4f => visitor.visit_i32_ge_u(),
985 0x50 => visitor.visit_i64_eqz(),
986 0x51 => visitor.visit_i64_eq(),
987 0x52 => visitor.visit_i64_ne(),
988 0x53 => visitor.visit_i64_lt_s(),
989 0x54 => visitor.visit_i64_lt_u(),
990 0x55 => visitor.visit_i64_gt_s(),
991 0x56 => visitor.visit_i64_gt_u(),
992 0x57 => visitor.visit_i64_le_s(),
993 0x58 => visitor.visit_i64_le_u(),
994 0x59 => visitor.visit_i64_ge_s(),
995 0x5a => visitor.visit_i64_ge_u(),
996 0x5b => visitor.visit_f32_eq(),
997 0x5c => visitor.visit_f32_ne(),
998 0x5d => visitor.visit_f32_lt(),
999 0x5e => visitor.visit_f32_gt(),
1000 0x5f => visitor.visit_f32_le(),
1001 0x60 => visitor.visit_f32_ge(),
1002 0x61 => visitor.visit_f64_eq(),
1003 0x62 => visitor.visit_f64_ne(),
1004 0x63 => visitor.visit_f64_lt(),
1005 0x64 => visitor.visit_f64_gt(),
1006 0x65 => visitor.visit_f64_le(),
1007 0x66 => visitor.visit_f64_ge(),
1008 0x67 => visitor.visit_i32_clz(),
1009 0x68 => visitor.visit_i32_ctz(),
1010 0x69 => visitor.visit_i32_popcnt(),
1011 0x6a => visitor.visit_i32_add(),
1012 0x6b => visitor.visit_i32_sub(),
1013 0x6c => visitor.visit_i32_mul(),
1014 0x6d => visitor.visit_i32_div_s(),
1015 0x6e => visitor.visit_i32_div_u(),
1016 0x6f => visitor.visit_i32_rem_s(),
1017 0x70 => visitor.visit_i32_rem_u(),
1018 0x71 => visitor.visit_i32_and(),
1019 0x72 => visitor.visit_i32_or(),
1020 0x73 => visitor.visit_i32_xor(),
1021 0x74 => visitor.visit_i32_shl(),
1022 0x75 => visitor.visit_i32_shr_s(),
1023 0x76 => visitor.visit_i32_shr_u(),
1024 0x77 => visitor.visit_i32_rotl(),
1025 0x78 => visitor.visit_i32_rotr(),
1026 0x79 => visitor.visit_i64_clz(),
1027 0x7a => visitor.visit_i64_ctz(),
1028 0x7b => visitor.visit_i64_popcnt(),
1029 0x7c => visitor.visit_i64_add(),
1030 0x7d => visitor.visit_i64_sub(),
1031 0x7e => visitor.visit_i64_mul(),
1032 0x7f => visitor.visit_i64_div_s(),
1033 0x80 => visitor.visit_i64_div_u(),
1034 0x81 => visitor.visit_i64_rem_s(),
1035 0x82 => visitor.visit_i64_rem_u(),
1036 0x83 => visitor.visit_i64_and(),
1037 0x84 => visitor.visit_i64_or(),
1038 0x85 => visitor.visit_i64_xor(),
1039 0x86 => visitor.visit_i64_shl(),
1040 0x87 => visitor.visit_i64_shr_s(),
1041 0x88 => visitor.visit_i64_shr_u(),
1042 0x89 => visitor.visit_i64_rotl(),
1043 0x8a => visitor.visit_i64_rotr(),
1044 0x8b => visitor.visit_f32_abs(),
1045 0x8c => visitor.visit_f32_neg(),
1046 0x8d => visitor.visit_f32_ceil(),
1047 0x8e => visitor.visit_f32_floor(),
1048 0x8f => visitor.visit_f32_trunc(),
1049 0x90 => visitor.visit_f32_nearest(),
1050 0x91 => visitor.visit_f32_sqrt(),
1051 0x92 => visitor.visit_f32_add(),
1052 0x93 => visitor.visit_f32_sub(),
1053 0x94 => visitor.visit_f32_mul(),
1054 0x95 => visitor.visit_f32_div(),
1055 0x96 => visitor.visit_f32_min(),
1056 0x97 => visitor.visit_f32_max(),
1057 0x98 => visitor.visit_f32_copysign(),
1058 0x99 => visitor.visit_f64_abs(),
1059 0x9a => visitor.visit_f64_neg(),
1060 0x9b => visitor.visit_f64_ceil(),
1061 0x9c => visitor.visit_f64_floor(),
1062 0x9d => visitor.visit_f64_trunc(),
1063 0x9e => visitor.visit_f64_nearest(),
1064 0x9f => visitor.visit_f64_sqrt(),
1065 0xa0 => visitor.visit_f64_add(),
1066 0xa1 => visitor.visit_f64_sub(),
1067 0xa2 => visitor.visit_f64_mul(),
1068 0xa3 => visitor.visit_f64_div(),
1069 0xa4 => visitor.visit_f64_min(),
1070 0xa5 => visitor.visit_f64_max(),
1071 0xa6 => visitor.visit_f64_copysign(),
1072 0xa7 => visitor.visit_i32_wrap_i64(),
1073 0xa8 => visitor.visit_i32_trunc_f32_s(),
1074 0xa9 => visitor.visit_i32_trunc_f32_u(),
1075 0xaa => visitor.visit_i32_trunc_f64_s(),
1076 0xab => visitor.visit_i32_trunc_f64_u(),
1077 0xac => visitor.visit_i64_extend_i32_s(),
1078 0xad => visitor.visit_i64_extend_i32_u(),
1079 0xae => visitor.visit_i64_trunc_f32_s(),
1080 0xaf => visitor.visit_i64_trunc_f32_u(),
1081 0xb0 => visitor.visit_i64_trunc_f64_s(),
1082 0xb1 => visitor.visit_i64_trunc_f64_u(),
1083 0xb2 => visitor.visit_f32_convert_i32_s(),
1084 0xb3 => visitor.visit_f32_convert_i32_u(),
1085 0xb4 => visitor.visit_f32_convert_i64_s(),
1086 0xb5 => visitor.visit_f32_convert_i64_u(),
1087 0xb6 => visitor.visit_f32_demote_f64(),
1088 0xb7 => visitor.visit_f64_convert_i32_s(),
1089 0xb8 => visitor.visit_f64_convert_i32_u(),
1090 0xb9 => visitor.visit_f64_convert_i64_s(),
1091 0xba => visitor.visit_f64_convert_i64_u(),
1092 0xbb => visitor.visit_f64_promote_f32(),
1093 0xbc => visitor.visit_i32_reinterpret_f32(),
1094 0xbd => visitor.visit_i64_reinterpret_f64(),
1095 0xbe => visitor.visit_f32_reinterpret_i32(),
1096 0xbf => visitor.visit_f64_reinterpret_i64(),
1097
1098 0xc0 => visitor.visit_i32_extend8_s(),
1099 0xc1 => visitor.visit_i32_extend16_s(),
1100 0xc2 => visitor.visit_i64_extend8_s(),
1101 0xc3 => visitor.visit_i64_extend16_s(),
1102 0xc4 => visitor.visit_i64_extend32_s(),
1103
1104 0xd0 => visitor.visit_ref_null(self.read()?),
1105 0xd1 => visitor.visit_ref_is_null(),
1106 0xd2 => visitor.visit_ref_func(self.read_var_u32()?),
1107 0xd3 => visitor.visit_ref_eq(),
1108 0xd4 => visitor.visit_ref_as_non_null(),
1109 0xd5 => visitor.visit_br_on_null(self.read_var_u32()?),
1110 0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?),
1111
1112 0xe0 => visitor.visit_cont_new(self.read_var_u32()?),
1113 0xe1 => visitor.visit_cont_bind(self.read_var_u32()?, self.read_var_u32()?),
1114 0xe2 => visitor.visit_suspend(self.read_var_u32()?),
1115 0xe3 => visitor.visit_resume(self.read_var_u32()?, self.read()?),
1116 0xe4 => {
1117 visitor.visit_resume_throw(self.read_var_u32()?, self.read_var_u32()?, self.read()?)
1118 }
1119 0xe5 => visitor.visit_switch(self.read_var_u32()?, self.read_var_u32()?),
1120
1121 0xfb => self.visit_0xfb_operator(pos, visitor)?,
1122 0xfc => self.visit_0xfc_operator(pos, visitor)?,
1123 0xfd => self.visit_0xfd_operator(pos, visitor)?,
1124 0xfe => self.visit_0xfe_operator(pos, visitor)?,
1125
1126 _ => bail!(pos, "illegal opcode: 0x{code:x}"),
1127 })
1128 }
1129
1130 fn visit_0xfb_operator<T>(
1131 &mut self,
1132 pos: usize,
1133 visitor: &mut T,
1134 ) -> Result<<T as VisitOperator<'a>>::Output>
1135 where
1136 T: VisitOperator<'a>,
1137 {
1138 let code = self.read_var_u32()?;
1139 Ok(match code {
1140 0x0 => {
1141 let type_index = self.read_var_u32()?;
1142 visitor.visit_struct_new(type_index)
1143 }
1144 0x01 => {
1145 let type_index = self.read_var_u32()?;
1146 visitor.visit_struct_new_default(type_index)
1147 }
1148 0x02 => {
1149 let type_index = self.read_var_u32()?;
1150 let field_index = self.read_var_u32()?;
1151 visitor.visit_struct_get(type_index, field_index)
1152 }
1153 0x03 => {
1154 let type_index = self.read_var_u32()?;
1155 let field_index = self.read_var_u32()?;
1156 visitor.visit_struct_get_s(type_index, field_index)
1157 }
1158 0x04 => {
1159 let type_index = self.read_var_u32()?;
1160 let field_index = self.read_var_u32()?;
1161 visitor.visit_struct_get_u(type_index, field_index)
1162 }
1163 0x05 => {
1164 let type_index = self.read_var_u32()?;
1165 let field_index = self.read_var_u32()?;
1166 visitor.visit_struct_set(type_index, field_index)
1167 }
1168 0x06 => {
1169 let type_index = self.read_var_u32()?;
1170 visitor.visit_array_new(type_index)
1171 }
1172 0x07 => {
1173 let type_index = self.read_var_u32()?;
1174 visitor.visit_array_new_default(type_index)
1175 }
1176 0x08 => {
1177 let type_index = self.read_var_u32()?;
1178 let n = self.read_var_u32()?;
1179 visitor.visit_array_new_fixed(type_index, n)
1180 }
1181 0x09 => {
1182 let type_index = self.read_var_u32()?;
1183 let data_index = self.read_var_u32()?;
1184 visitor.visit_array_new_data(type_index, data_index)
1185 }
1186 0x0a => {
1187 let type_index = self.read_var_u32()?;
1188 let elem_index = self.read_var_u32()?;
1189 visitor.visit_array_new_elem(type_index, elem_index)
1190 }
1191 0x0b => {
1192 let type_index = self.read_var_u32()?;
1193 visitor.visit_array_get(type_index)
1194 }
1195 0x0c => {
1196 let type_index = self.read_var_u32()?;
1197 visitor.visit_array_get_s(type_index)
1198 }
1199 0x0d => {
1200 let type_index = self.read_var_u32()?;
1201 visitor.visit_array_get_u(type_index)
1202 }
1203 0x0e => {
1204 let type_index = self.read_var_u32()?;
1205 visitor.visit_array_set(type_index)
1206 }
1207 0x0f => visitor.visit_array_len(),
1208 0x10 => {
1209 let type_index = self.read_var_u32()?;
1210 visitor.visit_array_fill(type_index)
1211 }
1212 0x11 => {
1213 let type_index_dst = self.read_var_u32()?;
1214 let type_index_src = self.read_var_u32()?;
1215 visitor.visit_array_copy(type_index_dst, type_index_src)
1216 }
1217 0x12 => {
1218 let type_index = self.read_var_u32()?;
1219 let data_index = self.read_var_u32()?;
1220 visitor.visit_array_init_data(type_index, data_index)
1221 }
1222 0x13 => {
1223 let type_index = self.read_var_u32()?;
1224 let elem_index = self.read_var_u32()?;
1225 visitor.visit_array_init_elem(type_index, elem_index)
1226 }
1227 0x14 => visitor.visit_ref_test_non_null(self.read()?),
1228 0x15 => visitor.visit_ref_test_nullable(self.read()?),
1229 0x16 => visitor.visit_ref_cast_non_null(self.read()?),
1230 0x17 => visitor.visit_ref_cast_nullable(self.read()?),
1231 0x18 => {
1232 let pos = self.original_position();
1233 let cast_flags = self.read_u8()?;
1234 let relative_depth = self.read_var_u32()?;
1235 let (from_type_nullable, to_type_nullable) = match cast_flags {
1236 0b00 => (false, false),
1237 0b01 => (true, false),
1238 0b10 => (false, true),
1239 0b11 => (true, true),
1240 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1241 };
1242 let from_heap_type = self.read()?;
1243 let from_ref_type =
1244 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1245 format_err!(pos, "implementation error: type index too large")
1246 })?;
1247 let to_heap_type = self.read()?;
1248 let to_ref_type =
1249 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1250 format_err!(pos, "implementation error: type index too large")
1251 })?;
1252 visitor.visit_br_on_cast(relative_depth, from_ref_type, to_ref_type)
1253 }
1254 0x19 => {
1255 let pos = self.original_position();
1256 let cast_flags = self.read_u8()?;
1257 let relative_depth = self.read_var_u32()?;
1258 let (from_type_nullable, to_type_nullable) = match cast_flags {
1259 0 => (false, false),
1260 1 => (true, false),
1261 2 => (false, true),
1262 3 => (true, true),
1263 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1264 };
1265 let from_heap_type = self.read()?;
1266 let from_ref_type =
1267 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1268 format_err!(pos, "implementation error: type index too large")
1269 })?;
1270 let to_heap_type = self.read()?;
1271 let to_ref_type =
1272 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1273 format_err!(pos, "implementation error: type index too large")
1274 })?;
1275 visitor.visit_br_on_cast_fail(relative_depth, from_ref_type, to_ref_type)
1276 }
1277
1278 0x1a => visitor.visit_any_convert_extern(),
1279 0x1b => visitor.visit_extern_convert_any(),
1280
1281 0x1c => visitor.visit_ref_i31(),
1282 0x1d => visitor.visit_i31_get_s(),
1283 0x1e => visitor.visit_i31_get_u(),
1284
1285 _ => bail!(pos, "unknown 0xfb subopcode: 0x{code:x}"),
1286 })
1287 }
1288
1289 fn visit_0xfc_operator<T>(
1290 &mut self,
1291 pos: usize,
1292 visitor: &mut T,
1293 ) -> Result<<T as VisitOperator<'a>>::Output>
1294 where
1295 T: VisitOperator<'a>,
1296 {
1297 let code = self.read_var_u32()?;
1298 Ok(match code {
1299 0x00 => visitor.visit_i32_trunc_sat_f32_s(),
1300 0x01 => visitor.visit_i32_trunc_sat_f32_u(),
1301 0x02 => visitor.visit_i32_trunc_sat_f64_s(),
1302 0x03 => visitor.visit_i32_trunc_sat_f64_u(),
1303 0x04 => visitor.visit_i64_trunc_sat_f32_s(),
1304 0x05 => visitor.visit_i64_trunc_sat_f32_u(),
1305 0x06 => visitor.visit_i64_trunc_sat_f64_s(),
1306 0x07 => visitor.visit_i64_trunc_sat_f64_u(),
1307
1308 0x08 => {
1309 let segment = self.read_var_u32()?;
1310 let mem = self.read_var_u32()?;
1311 visitor.visit_memory_init(segment, mem)
1312 }
1313 0x09 => {
1314 let segment = self.read_var_u32()?;
1315 visitor.visit_data_drop(segment)
1316 }
1317 0x0a => {
1318 let dst = self.read_var_u32()?;
1319 let src = self.read_var_u32()?;
1320 visitor.visit_memory_copy(dst, src)
1321 }
1322 0x0b => {
1323 let mem = self.read_var_u32()?;
1324 visitor.visit_memory_fill(mem)
1325 }
1326 0x0c => {
1327 let segment = self.read_var_u32()?;
1328 let table = self.read_var_u32()?;
1329 visitor.visit_table_init(segment, table)
1330 }
1331 0x0d => {
1332 let segment = self.read_var_u32()?;
1333 visitor.visit_elem_drop(segment)
1334 }
1335 0x0e => {
1336 let dst_table = self.read_var_u32()?;
1337 let src_table = self.read_var_u32()?;
1338 visitor.visit_table_copy(dst_table, src_table)
1339 }
1340
1341 0x0f => {
1342 let table = self.read_var_u32()?;
1343 visitor.visit_table_grow(table)
1344 }
1345 0x10 => {
1346 let table = self.read_var_u32()?;
1347 visitor.visit_table_size(table)
1348 }
1349
1350 0x11 => {
1351 let table = self.read_var_u32()?;
1352 visitor.visit_table_fill(table)
1353 }
1354
1355 0x12 => {
1356 let mem = self.read_var_u32()?;
1357 visitor.visit_memory_discard(mem)
1358 }
1359
1360 0x13 => visitor.visit_i64_add128(),
1361 0x14 => visitor.visit_i64_sub128(),
1362 0x15 => visitor.visit_i64_mul_wide_s(),
1363 0x16 => visitor.visit_i64_mul_wide_u(),
1364
1365 _ => bail!(pos, "unknown 0xfc subopcode: 0x{code:x}"),
1366 })
1367 }
1368
1369 fn visit_0xfd_operator<T>(
1370 &mut self,
1371 pos: usize,
1372 visitor: &mut T,
1373 ) -> Result<<T as VisitOperator<'a>>::Output>
1374 where
1375 T: VisitOperator<'a>,
1376 {
1377 let code = self.read_var_u32()?;
1378 Ok(match code {
1379 0x00 => visitor.visit_v128_load(self.read_memarg(4)?),
1380 0x01 => visitor.visit_v128_load8x8_s(self.read_memarg(3)?),
1381 0x02 => visitor.visit_v128_load8x8_u(self.read_memarg(3)?),
1382 0x03 => visitor.visit_v128_load16x4_s(self.read_memarg(3)?),
1383 0x04 => visitor.visit_v128_load16x4_u(self.read_memarg(3)?),
1384 0x05 => visitor.visit_v128_load32x2_s(self.read_memarg(3)?),
1385 0x06 => visitor.visit_v128_load32x2_u(self.read_memarg(3)?),
1386 0x07 => visitor.visit_v128_load8_splat(self.read_memarg(0)?),
1387 0x08 => visitor.visit_v128_load16_splat(self.read_memarg(1)?),
1388 0x09 => visitor.visit_v128_load32_splat(self.read_memarg(2)?),
1389 0x0a => visitor.visit_v128_load64_splat(self.read_memarg(3)?),
1390
1391 0x0b => visitor.visit_v128_store(self.read_memarg(4)?),
1392 0x0c => visitor.visit_v128_const(self.read_v128()?),
1393 0x0d => {
1394 let mut lanes: [u8; 16] = [0; 16];
1395 for lane in &mut lanes {
1396 *lane = self.read_lane_index(32)?
1397 }
1398 visitor.visit_i8x16_shuffle(lanes)
1399 }
1400
1401 0x0e => visitor.visit_i8x16_swizzle(),
1402 0x0f => visitor.visit_i8x16_splat(),
1403 0x10 => visitor.visit_i16x8_splat(),
1404 0x11 => visitor.visit_i32x4_splat(),
1405 0x12 => visitor.visit_i64x2_splat(),
1406 0x13 => visitor.visit_f32x4_splat(),
1407 0x14 => visitor.visit_f64x2_splat(),
1408
1409 0x15 => visitor.visit_i8x16_extract_lane_s(self.read_lane_index(16)?),
1410 0x16 => visitor.visit_i8x16_extract_lane_u(self.read_lane_index(16)?),
1411 0x17 => visitor.visit_i8x16_replace_lane(self.read_lane_index(16)?),
1412 0x18 => visitor.visit_i16x8_extract_lane_s(self.read_lane_index(8)?),
1413 0x19 => visitor.visit_i16x8_extract_lane_u(self.read_lane_index(8)?),
1414 0x1a => visitor.visit_i16x8_replace_lane(self.read_lane_index(8)?),
1415 0x1b => visitor.visit_i32x4_extract_lane(self.read_lane_index(4)?),
1416
1417 0x1c => visitor.visit_i32x4_replace_lane(self.read_lane_index(4)?),
1418 0x1d => visitor.visit_i64x2_extract_lane(self.read_lane_index(2)?),
1419 0x1e => visitor.visit_i64x2_replace_lane(self.read_lane_index(2)?),
1420 0x1f => visitor.visit_f32x4_extract_lane(self.read_lane_index(4)?),
1421 0x20 => visitor.visit_f32x4_replace_lane(self.read_lane_index(4)?),
1422 0x21 => visitor.visit_f64x2_extract_lane(self.read_lane_index(2)?),
1423 0x22 => visitor.visit_f64x2_replace_lane(self.read_lane_index(2)?),
1424
1425 0x23 => visitor.visit_i8x16_eq(),
1426 0x24 => visitor.visit_i8x16_ne(),
1427 0x25 => visitor.visit_i8x16_lt_s(),
1428 0x26 => visitor.visit_i8x16_lt_u(),
1429 0x27 => visitor.visit_i8x16_gt_s(),
1430 0x28 => visitor.visit_i8x16_gt_u(),
1431 0x29 => visitor.visit_i8x16_le_s(),
1432 0x2a => visitor.visit_i8x16_le_u(),
1433 0x2b => visitor.visit_i8x16_ge_s(),
1434 0x2c => visitor.visit_i8x16_ge_u(),
1435 0x2d => visitor.visit_i16x8_eq(),
1436 0x2e => visitor.visit_i16x8_ne(),
1437 0x2f => visitor.visit_i16x8_lt_s(),
1438 0x30 => visitor.visit_i16x8_lt_u(),
1439 0x31 => visitor.visit_i16x8_gt_s(),
1440 0x32 => visitor.visit_i16x8_gt_u(),
1441 0x33 => visitor.visit_i16x8_le_s(),
1442 0x34 => visitor.visit_i16x8_le_u(),
1443 0x35 => visitor.visit_i16x8_ge_s(),
1444 0x36 => visitor.visit_i16x8_ge_u(),
1445 0x37 => visitor.visit_i32x4_eq(),
1446 0x38 => visitor.visit_i32x4_ne(),
1447 0x39 => visitor.visit_i32x4_lt_s(),
1448 0x3a => visitor.visit_i32x4_lt_u(),
1449 0x3b => visitor.visit_i32x4_gt_s(),
1450 0x3c => visitor.visit_i32x4_gt_u(),
1451 0x3d => visitor.visit_i32x4_le_s(),
1452 0x3e => visitor.visit_i32x4_le_u(),
1453 0x3f => visitor.visit_i32x4_ge_s(),
1454 0x40 => visitor.visit_i32x4_ge_u(),
1455 0x41 => visitor.visit_f32x4_eq(),
1456 0x42 => visitor.visit_f32x4_ne(),
1457 0x43 => visitor.visit_f32x4_lt(),
1458 0x44 => visitor.visit_f32x4_gt(),
1459 0x45 => visitor.visit_f32x4_le(),
1460 0x46 => visitor.visit_f32x4_ge(),
1461 0x47 => visitor.visit_f64x2_eq(),
1462 0x48 => visitor.visit_f64x2_ne(),
1463 0x49 => visitor.visit_f64x2_lt(),
1464 0x4a => visitor.visit_f64x2_gt(),
1465 0x4b => visitor.visit_f64x2_le(),
1466 0x4c => visitor.visit_f64x2_ge(),
1467 0x4d => visitor.visit_v128_not(),
1468 0x4e => visitor.visit_v128_and(),
1469 0x4f => visitor.visit_v128_andnot(),
1470 0x50 => visitor.visit_v128_or(),
1471 0x51 => visitor.visit_v128_xor(),
1472 0x52 => visitor.visit_v128_bitselect(),
1473 0x53 => visitor.visit_v128_any_true(),
1474
1475 0x54 => {
1476 let memarg = self.read_memarg(0)?;
1477 let lane = self.read_lane_index(16)?;
1478 visitor.visit_v128_load8_lane(memarg, lane)
1479 }
1480 0x55 => {
1481 let memarg = self.read_memarg(1)?;
1482 let lane = self.read_lane_index(8)?;
1483 visitor.visit_v128_load16_lane(memarg, lane)
1484 }
1485 0x56 => {
1486 let memarg = self.read_memarg(2)?;
1487 let lane = self.read_lane_index(4)?;
1488 visitor.visit_v128_load32_lane(memarg, lane)
1489 }
1490 0x57 => {
1491 let memarg = self.read_memarg(3)?;
1492 let lane = self.read_lane_index(2)?;
1493 visitor.visit_v128_load64_lane(memarg, lane)
1494 }
1495 0x58 => {
1496 let memarg = self.read_memarg(0)?;
1497 let lane = self.read_lane_index(16)?;
1498 visitor.visit_v128_store8_lane(memarg, lane)
1499 }
1500 0x59 => {
1501 let memarg = self.read_memarg(1)?;
1502 let lane = self.read_lane_index(8)?;
1503 visitor.visit_v128_store16_lane(memarg, lane)
1504 }
1505 0x5a => {
1506 let memarg = self.read_memarg(2)?;
1507 let lane = self.read_lane_index(4)?;
1508 visitor.visit_v128_store32_lane(memarg, lane)
1509 }
1510 0x5b => {
1511 let memarg = self.read_memarg(3)?;
1512 let lane = self.read_lane_index(2)?;
1513 visitor.visit_v128_store64_lane(memarg, lane)
1514 }
1515
1516 0x5c => visitor.visit_v128_load32_zero(self.read_memarg(2)?),
1517 0x5d => visitor.visit_v128_load64_zero(self.read_memarg(3)?),
1518 0x5e => visitor.visit_f32x4_demote_f64x2_zero(),
1519 0x5f => visitor.visit_f64x2_promote_low_f32x4(),
1520 0x60 => visitor.visit_i8x16_abs(),
1521 0x61 => visitor.visit_i8x16_neg(),
1522 0x62 => visitor.visit_i8x16_popcnt(),
1523 0x63 => visitor.visit_i8x16_all_true(),
1524 0x64 => visitor.visit_i8x16_bitmask(),
1525 0x65 => visitor.visit_i8x16_narrow_i16x8_s(),
1526 0x66 => visitor.visit_i8x16_narrow_i16x8_u(),
1527 0x67 => visitor.visit_f32x4_ceil(),
1528 0x68 => visitor.visit_f32x4_floor(),
1529 0x69 => visitor.visit_f32x4_trunc(),
1530 0x6a => visitor.visit_f32x4_nearest(),
1531 0x6b => visitor.visit_i8x16_shl(),
1532 0x6c => visitor.visit_i8x16_shr_s(),
1533 0x6d => visitor.visit_i8x16_shr_u(),
1534 0x6e => visitor.visit_i8x16_add(),
1535 0x6f => visitor.visit_i8x16_add_sat_s(),
1536 0x70 => visitor.visit_i8x16_add_sat_u(),
1537 0x71 => visitor.visit_i8x16_sub(),
1538 0x72 => visitor.visit_i8x16_sub_sat_s(),
1539 0x73 => visitor.visit_i8x16_sub_sat_u(),
1540 0x74 => visitor.visit_f64x2_ceil(),
1541 0x75 => visitor.visit_f64x2_floor(),
1542 0x76 => visitor.visit_i8x16_min_s(),
1543 0x77 => visitor.visit_i8x16_min_u(),
1544 0x78 => visitor.visit_i8x16_max_s(),
1545 0x79 => visitor.visit_i8x16_max_u(),
1546 0x7a => visitor.visit_f64x2_trunc(),
1547 0x7b => visitor.visit_i8x16_avgr_u(),
1548 0x7c => visitor.visit_i16x8_extadd_pairwise_i8x16_s(),
1549 0x7d => visitor.visit_i16x8_extadd_pairwise_i8x16_u(),
1550 0x7e => visitor.visit_i32x4_extadd_pairwise_i16x8_s(),
1551 0x7f => visitor.visit_i32x4_extadd_pairwise_i16x8_u(),
1552 0x80 => visitor.visit_i16x8_abs(),
1553 0x81 => visitor.visit_i16x8_neg(),
1554 0x82 => visitor.visit_i16x8_q15mulr_sat_s(),
1555 0x83 => visitor.visit_i16x8_all_true(),
1556 0x84 => visitor.visit_i16x8_bitmask(),
1557 0x85 => visitor.visit_i16x8_narrow_i32x4_s(),
1558 0x86 => visitor.visit_i16x8_narrow_i32x4_u(),
1559 0x87 => visitor.visit_i16x8_extend_low_i8x16_s(),
1560 0x88 => visitor.visit_i16x8_extend_high_i8x16_s(),
1561 0x89 => visitor.visit_i16x8_extend_low_i8x16_u(),
1562 0x8a => visitor.visit_i16x8_extend_high_i8x16_u(),
1563 0x8b => visitor.visit_i16x8_shl(),
1564 0x8c => visitor.visit_i16x8_shr_s(),
1565 0x8d => visitor.visit_i16x8_shr_u(),
1566 0x8e => visitor.visit_i16x8_add(),
1567 0x8f => visitor.visit_i16x8_add_sat_s(),
1568 0x90 => visitor.visit_i16x8_add_sat_u(),
1569 0x91 => visitor.visit_i16x8_sub(),
1570 0x92 => visitor.visit_i16x8_sub_sat_s(),
1571 0x93 => visitor.visit_i16x8_sub_sat_u(),
1572 0x94 => visitor.visit_f64x2_nearest(),
1573 0x95 => visitor.visit_i16x8_mul(),
1574 0x96 => visitor.visit_i16x8_min_s(),
1575 0x97 => visitor.visit_i16x8_min_u(),
1576 0x98 => visitor.visit_i16x8_max_s(),
1577 0x99 => visitor.visit_i16x8_max_u(),
1578 0x9b => visitor.visit_i16x8_avgr_u(),
1579 0x9c => visitor.visit_i16x8_extmul_low_i8x16_s(),
1580 0x9d => visitor.visit_i16x8_extmul_high_i8x16_s(),
1581 0x9e => visitor.visit_i16x8_extmul_low_i8x16_u(),
1582 0x9f => visitor.visit_i16x8_extmul_high_i8x16_u(),
1583 0xa0 => visitor.visit_i32x4_abs(),
1584 0xa1 => visitor.visit_i32x4_neg(),
1585 0xa3 => visitor.visit_i32x4_all_true(),
1586 0xa4 => visitor.visit_i32x4_bitmask(),
1587 0xa7 => visitor.visit_i32x4_extend_low_i16x8_s(),
1588 0xa8 => visitor.visit_i32x4_extend_high_i16x8_s(),
1589 0xa9 => visitor.visit_i32x4_extend_low_i16x8_u(),
1590 0xaa => visitor.visit_i32x4_extend_high_i16x8_u(),
1591 0xab => visitor.visit_i32x4_shl(),
1592 0xac => visitor.visit_i32x4_shr_s(),
1593 0xad => visitor.visit_i32x4_shr_u(),
1594 0xae => visitor.visit_i32x4_add(),
1595 0xb1 => visitor.visit_i32x4_sub(),
1596 0xb5 => visitor.visit_i32x4_mul(),
1597 0xb6 => visitor.visit_i32x4_min_s(),
1598 0xb7 => visitor.visit_i32x4_min_u(),
1599 0xb8 => visitor.visit_i32x4_max_s(),
1600 0xb9 => visitor.visit_i32x4_max_u(),
1601 0xba => visitor.visit_i32x4_dot_i16x8_s(),
1602 0xbc => visitor.visit_i32x4_extmul_low_i16x8_s(),
1603 0xbd => visitor.visit_i32x4_extmul_high_i16x8_s(),
1604 0xbe => visitor.visit_i32x4_extmul_low_i16x8_u(),
1605 0xbf => visitor.visit_i32x4_extmul_high_i16x8_u(),
1606 0xc0 => visitor.visit_i64x2_abs(),
1607 0xc1 => visitor.visit_i64x2_neg(),
1608 0xc3 => visitor.visit_i64x2_all_true(),
1609 0xc4 => visitor.visit_i64x2_bitmask(),
1610 0xc7 => visitor.visit_i64x2_extend_low_i32x4_s(),
1611 0xc8 => visitor.visit_i64x2_extend_high_i32x4_s(),
1612 0xc9 => visitor.visit_i64x2_extend_low_i32x4_u(),
1613 0xca => visitor.visit_i64x2_extend_high_i32x4_u(),
1614 0xcb => visitor.visit_i64x2_shl(),
1615 0xcc => visitor.visit_i64x2_shr_s(),
1616 0xcd => visitor.visit_i64x2_shr_u(),
1617 0xce => visitor.visit_i64x2_add(),
1618 0xd1 => visitor.visit_i64x2_sub(),
1619 0xd5 => visitor.visit_i64x2_mul(),
1620 0xd6 => visitor.visit_i64x2_eq(),
1621 0xd7 => visitor.visit_i64x2_ne(),
1622 0xd8 => visitor.visit_i64x2_lt_s(),
1623 0xd9 => visitor.visit_i64x2_gt_s(),
1624 0xda => visitor.visit_i64x2_le_s(),
1625 0xdb => visitor.visit_i64x2_ge_s(),
1626 0xdc => visitor.visit_i64x2_extmul_low_i32x4_s(),
1627 0xdd => visitor.visit_i64x2_extmul_high_i32x4_s(),
1628 0xde => visitor.visit_i64x2_extmul_low_i32x4_u(),
1629 0xdf => visitor.visit_i64x2_extmul_high_i32x4_u(),
1630 0xe0 => visitor.visit_f32x4_abs(),
1631 0xe1 => visitor.visit_f32x4_neg(),
1632 0xe3 => visitor.visit_f32x4_sqrt(),
1633 0xe4 => visitor.visit_f32x4_add(),
1634 0xe5 => visitor.visit_f32x4_sub(),
1635 0xe6 => visitor.visit_f32x4_mul(),
1636 0xe7 => visitor.visit_f32x4_div(),
1637 0xe8 => visitor.visit_f32x4_min(),
1638 0xe9 => visitor.visit_f32x4_max(),
1639 0xea => visitor.visit_f32x4_pmin(),
1640 0xeb => visitor.visit_f32x4_pmax(),
1641 0xec => visitor.visit_f64x2_abs(),
1642 0xed => visitor.visit_f64x2_neg(),
1643 0xef => visitor.visit_f64x2_sqrt(),
1644 0xf0 => visitor.visit_f64x2_add(),
1645 0xf1 => visitor.visit_f64x2_sub(),
1646 0xf2 => visitor.visit_f64x2_mul(),
1647 0xf3 => visitor.visit_f64x2_div(),
1648 0xf4 => visitor.visit_f64x2_min(),
1649 0xf5 => visitor.visit_f64x2_max(),
1650 0xf6 => visitor.visit_f64x2_pmin(),
1651 0xf7 => visitor.visit_f64x2_pmax(),
1652 0xf8 => visitor.visit_i32x4_trunc_sat_f32x4_s(),
1653 0xf9 => visitor.visit_i32x4_trunc_sat_f32x4_u(),
1654 0xfa => visitor.visit_f32x4_convert_i32x4_s(),
1655 0xfb => visitor.visit_f32x4_convert_i32x4_u(),
1656 0xfc => visitor.visit_i32x4_trunc_sat_f64x2_s_zero(),
1657 0xfd => visitor.visit_i32x4_trunc_sat_f64x2_u_zero(),
1658 0xfe => visitor.visit_f64x2_convert_low_i32x4_s(),
1659 0xff => visitor.visit_f64x2_convert_low_i32x4_u(),
1660 0x100 => visitor.visit_i8x16_relaxed_swizzle(),
1661 0x101 => visitor.visit_i32x4_relaxed_trunc_f32x4_s(),
1662 0x102 => visitor.visit_i32x4_relaxed_trunc_f32x4_u(),
1663 0x103 => visitor.visit_i32x4_relaxed_trunc_f64x2_s_zero(),
1664 0x104 => visitor.visit_i32x4_relaxed_trunc_f64x2_u_zero(),
1665 0x105 => visitor.visit_f32x4_relaxed_madd(),
1666 0x106 => visitor.visit_f32x4_relaxed_nmadd(),
1667 0x107 => visitor.visit_f64x2_relaxed_madd(),
1668 0x108 => visitor.visit_f64x2_relaxed_nmadd(),
1669 0x109 => visitor.visit_i8x16_relaxed_laneselect(),
1670 0x10a => visitor.visit_i16x8_relaxed_laneselect(),
1671 0x10b => visitor.visit_i32x4_relaxed_laneselect(),
1672 0x10c => visitor.visit_i64x2_relaxed_laneselect(),
1673 0x10d => visitor.visit_f32x4_relaxed_min(),
1674 0x10e => visitor.visit_f32x4_relaxed_max(),
1675 0x10f => visitor.visit_f64x2_relaxed_min(),
1676 0x110 => visitor.visit_f64x2_relaxed_max(),
1677 0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(),
1678 0x112 => visitor.visit_i16x8_relaxed_dot_i8x16_i7x16_s(),
1679 0x113 => visitor.visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(),
1680
1681 _ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"),
1682 })
1683 }
1684
1685 fn visit_0xfe_operator<T>(
1686 &mut self,
1687 pos: usize,
1688 visitor: &mut T,
1689 ) -> Result<<T as VisitOperator<'a>>::Output>
1690 where
1691 T: VisitOperator<'a>,
1692 {
1693 let code = self.read_var_u32()?;
1694 Ok(match code {
1695 0x00 => visitor.visit_memory_atomic_notify(self.read_memarg(2)?),
1696 0x01 => visitor.visit_memory_atomic_wait32(self.read_memarg(2)?),
1697 0x02 => visitor.visit_memory_atomic_wait64(self.read_memarg(3)?),
1698 0x03 => {
1699 if self.read_u8()? != 0 {
1700 bail!(pos, "nonzero byte after `atomic.fence`");
1701 }
1702 visitor.visit_atomic_fence()
1703 }
1704 0x10 => visitor.visit_i32_atomic_load(self.read_memarg(2)?),
1705 0x11 => visitor.visit_i64_atomic_load(self.read_memarg(3)?),
1706 0x12 => visitor.visit_i32_atomic_load8_u(self.read_memarg(0)?),
1707 0x13 => visitor.visit_i32_atomic_load16_u(self.read_memarg(1)?),
1708 0x14 => visitor.visit_i64_atomic_load8_u(self.read_memarg(0)?),
1709 0x15 => visitor.visit_i64_atomic_load16_u(self.read_memarg(1)?),
1710 0x16 => visitor.visit_i64_atomic_load32_u(self.read_memarg(2)?),
1711 0x17 => visitor.visit_i32_atomic_store(self.read_memarg(2)?),
1712 0x18 => visitor.visit_i64_atomic_store(self.read_memarg(3)?),
1713 0x19 => visitor.visit_i32_atomic_store8(self.read_memarg(0)?),
1714 0x1a => visitor.visit_i32_atomic_store16(self.read_memarg(1)?),
1715 0x1b => visitor.visit_i64_atomic_store8(self.read_memarg(0)?),
1716 0x1c => visitor.visit_i64_atomic_store16(self.read_memarg(1)?),
1717 0x1d => visitor.visit_i64_atomic_store32(self.read_memarg(2)?),
1718 0x1e => visitor.visit_i32_atomic_rmw_add(self.read_memarg(2)?),
1719 0x1f => visitor.visit_i64_atomic_rmw_add(self.read_memarg(3)?),
1720 0x20 => visitor.visit_i32_atomic_rmw8_add_u(self.read_memarg(0)?),
1721 0x21 => visitor.visit_i32_atomic_rmw16_add_u(self.read_memarg(1)?),
1722 0x22 => visitor.visit_i64_atomic_rmw8_add_u(self.read_memarg(0)?),
1723 0x23 => visitor.visit_i64_atomic_rmw16_add_u(self.read_memarg(1)?),
1724 0x24 => visitor.visit_i64_atomic_rmw32_add_u(self.read_memarg(2)?),
1725 0x25 => visitor.visit_i32_atomic_rmw_sub(self.read_memarg(2)?),
1726 0x26 => visitor.visit_i64_atomic_rmw_sub(self.read_memarg(3)?),
1727 0x27 => visitor.visit_i32_atomic_rmw8_sub_u(self.read_memarg(0)?),
1728 0x28 => visitor.visit_i32_atomic_rmw16_sub_u(self.read_memarg(1)?),
1729 0x29 => visitor.visit_i64_atomic_rmw8_sub_u(self.read_memarg(0)?),
1730 0x2a => visitor.visit_i64_atomic_rmw16_sub_u(self.read_memarg(1)?),
1731 0x2b => visitor.visit_i64_atomic_rmw32_sub_u(self.read_memarg(2)?),
1732 0x2c => visitor.visit_i32_atomic_rmw_and(self.read_memarg(2)?),
1733 0x2d => visitor.visit_i64_atomic_rmw_and(self.read_memarg(3)?),
1734 0x2e => visitor.visit_i32_atomic_rmw8_and_u(self.read_memarg(0)?),
1735 0x2f => visitor.visit_i32_atomic_rmw16_and_u(self.read_memarg(1)?),
1736 0x30 => visitor.visit_i64_atomic_rmw8_and_u(self.read_memarg(0)?),
1737 0x31 => visitor.visit_i64_atomic_rmw16_and_u(self.read_memarg(1)?),
1738 0x32 => visitor.visit_i64_atomic_rmw32_and_u(self.read_memarg(2)?),
1739 0x33 => visitor.visit_i32_atomic_rmw_or(self.read_memarg(2)?),
1740 0x34 => visitor.visit_i64_atomic_rmw_or(self.read_memarg(3)?),
1741 0x35 => visitor.visit_i32_atomic_rmw8_or_u(self.read_memarg(0)?),
1742 0x36 => visitor.visit_i32_atomic_rmw16_or_u(self.read_memarg(1)?),
1743 0x37 => visitor.visit_i64_atomic_rmw8_or_u(self.read_memarg(0)?),
1744 0x38 => visitor.visit_i64_atomic_rmw16_or_u(self.read_memarg(1)?),
1745 0x39 => visitor.visit_i64_atomic_rmw32_or_u(self.read_memarg(2)?),
1746 0x3a => visitor.visit_i32_atomic_rmw_xor(self.read_memarg(2)?),
1747 0x3b => visitor.visit_i64_atomic_rmw_xor(self.read_memarg(3)?),
1748 0x3c => visitor.visit_i32_atomic_rmw8_xor_u(self.read_memarg(0)?),
1749 0x3d => visitor.visit_i32_atomic_rmw16_xor_u(self.read_memarg(1)?),
1750 0x3e => visitor.visit_i64_atomic_rmw8_xor_u(self.read_memarg(0)?),
1751 0x3f => visitor.visit_i64_atomic_rmw16_xor_u(self.read_memarg(1)?),
1752 0x40 => visitor.visit_i64_atomic_rmw32_xor_u(self.read_memarg(2)?),
1753 0x41 => visitor.visit_i32_atomic_rmw_xchg(self.read_memarg(2)?),
1754 0x42 => visitor.visit_i64_atomic_rmw_xchg(self.read_memarg(3)?),
1755 0x43 => visitor.visit_i32_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1756 0x44 => visitor.visit_i32_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1757 0x45 => visitor.visit_i64_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1758 0x46 => visitor.visit_i64_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1759 0x47 => visitor.visit_i64_atomic_rmw32_xchg_u(self.read_memarg(2)?),
1760 0x48 => visitor.visit_i32_atomic_rmw_cmpxchg(self.read_memarg(2)?),
1761 0x49 => visitor.visit_i64_atomic_rmw_cmpxchg(self.read_memarg(3)?),
1762 0x4a => visitor.visit_i32_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1763 0x4b => visitor.visit_i32_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1764 0x4c => visitor.visit_i64_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1765 0x4d => visitor.visit_i64_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1766 0x4e => visitor.visit_i64_atomic_rmw32_cmpxchg_u(self.read_memarg(2)?),
1767
1768 // Decode shared-everything-threads proposal.
1769 0x4f => visitor.visit_global_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1770 0x50 => visitor.visit_global_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1771 0x51 => {
1772 visitor.visit_global_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?)
1773 }
1774 0x52 => {
1775 visitor.visit_global_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?)
1776 }
1777 0x53 => {
1778 visitor.visit_global_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?)
1779 }
1780 0x54 => visitor.visit_global_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?),
1781 0x55 => {
1782 visitor.visit_global_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?)
1783 }
1784 0x56 => {
1785 visitor.visit_global_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
1786 }
1787 0x57 => {
1788 visitor.visit_global_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
1789 }
1790 0x58 => visitor.visit_table_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1791 0x59 => visitor.visit_table_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1792 0x5a => {
1793 visitor.visit_table_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
1794 }
1795 0x5b => {
1796 visitor.visit_table_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
1797 }
1798 0x5c => visitor.visit_struct_atomic_get(
1799 self.read_ordering()?,
1800 self.read_var_u32()?,
1801 self.read_var_u32()?,
1802 ),
1803 0x5d => visitor.visit_struct_atomic_get_s(
1804 self.read_ordering()?,
1805 self.read_var_u32()?,
1806 self.read_var_u32()?,
1807 ),
1808 0x5e => visitor.visit_struct_atomic_get_u(
1809 self.read_ordering()?,
1810 self.read_var_u32()?,
1811 self.read_var_u32()?,
1812 ),
1813 0x5f => visitor.visit_struct_atomic_set(
1814 self.read_ordering()?,
1815 self.read_var_u32()?,
1816 self.read_var_u32()?,
1817 ),
1818 0x60 => visitor.visit_struct_atomic_rmw_add(
1819 self.read_ordering()?,
1820 self.read_var_u32()?,
1821 self.read_var_u32()?,
1822 ),
1823 0x61 => visitor.visit_struct_atomic_rmw_sub(
1824 self.read_ordering()?,
1825 self.read_var_u32()?,
1826 self.read_var_u32()?,
1827 ),
1828 0x62 => visitor.visit_struct_atomic_rmw_and(
1829 self.read_ordering()?,
1830 self.read_var_u32()?,
1831 self.read_var_u32()?,
1832 ),
1833 0x63 => visitor.visit_struct_atomic_rmw_or(
1834 self.read_ordering()?,
1835 self.read_var_u32()?,
1836 self.read_var_u32()?,
1837 ),
1838 0x64 => visitor.visit_struct_atomic_rmw_xor(
1839 self.read_ordering()?,
1840 self.read_var_u32()?,
1841 self.read_var_u32()?,
1842 ),
1843 0x65 => visitor.visit_struct_atomic_rmw_xchg(
1844 self.read_ordering()?,
1845 self.read_var_u32()?,
1846 self.read_var_u32()?,
1847 ),
1848 0x66 => visitor.visit_struct_atomic_rmw_cmpxchg(
1849 self.read_ordering()?,
1850 self.read_var_u32()?,
1851 self.read_var_u32()?,
1852 ),
1853 0x67 => visitor.visit_array_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1854 0x68 => visitor.visit_array_atomic_get_s(self.read_ordering()?, self.read_var_u32()?),
1855 0x69 => visitor.visit_array_atomic_get_u(self.read_ordering()?, self.read_var_u32()?),
1856 0x6a => visitor.visit_array_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1857 0x6b => visitor.visit_array_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?),
1858 0x6c => visitor.visit_array_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?),
1859 0x6d => visitor.visit_array_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?),
1860 0x6e => visitor.visit_array_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?),
1861 0x6f => visitor.visit_array_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?),
1862 0x70 => {
1863 visitor.visit_array_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
1864 }
1865 0x71 => {
1866 visitor.visit_array_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
1867 }
1868 0x72 => visitor.visit_ref_i31_shared(),
1869
1870 _ => bail!(pos, "unknown 0xfe subopcode: 0x{code:x}"),
1871 })
1872 }
1873
1874 /// Reads the next available `Operator`.
1875 ///
1876 /// # Errors
1877 ///
1878 /// If `BinaryReader` has less bytes remaining than required to parse
1879 /// the `Operator`.
1880 pub fn read_operator(&mut self) -> Result<Operator<'a>> {
1881 self.visit_operator(&mut OperatorFactory::new())
1882 }
1883
1884 /// Returns whether there is an `end` opcode followed by eof remaining in
1885 /// this reader.
1886 pub fn is_end_then_eof(&self) -> bool {
1887 self.remaining_buffer() == &[0x0b]
1888 }
1889
1890 fn read_lane_index(&mut self, max: u8) -> Result<u8> {
1891 let index = self.read_u8()?;
1892 if index >= max {
1893 return Err(BinaryReaderError::new(
1894 "invalid lane index",
1895 self.original_position() - 1,
1896 ));
1897 }
1898 Ok(index)
1899 }
1900
1901 fn read_v128(&mut self) -> Result<V128> {
1902 let mut bytes = [0; 16];
1903 bytes.clone_from_slice(self.read_bytes(16)?);
1904 Ok(V128(bytes))
1905 }
1906
1907 pub(crate) fn read_header_version(&mut self) -> Result<u32> {
1908 let magic_number = self.read_bytes(4)?;
1909 if magic_number != WASM_MAGIC_NUMBER {
1910 return Err(BinaryReaderError::new(
1911 format!("magic header not detected: bad magic number - expected={WASM_MAGIC_NUMBER:#x?} actual={magic_number:#x?}"),
1912 self.original_position() - 4,
1913 ));
1914 }
1915 self.read_u32()
1916 }
1917
1918 pub(crate) fn skip_const_expr(&mut self) -> Result<()> {
1919 // TODO add skip_operator() method and/or validate ConstExpr operators.
1920 loop {
1921 if let Operator::End = self.read_operator()? {
1922 return Ok(());
1923 }
1924 }
1925 }
1926
1927 fn read_memory_index_or_zero_if_not_multi_memory(&mut self) -> Result<u32> {
1928 if self.multi_memory() {
1929 self.read_var_u32()
1930 } else {
1931 // Before bulk memory this byte was required to be a single zero
1932 // byte, not a LEB-encoded zero, so require a precise zero byte.
1933 match self.read_u8()? {
1934 0 => Ok(0),
1935 _ => bail!(self.original_position() - 1, "zero byte expected"),
1936 }
1937 }
1938 }
1939
1940 fn read_table_index_or_zero_if_not_reference_types(&mut self) -> Result<u32> {
1941 if self.reference_types() {
1942 self.read_var_u32()
1943 } else {
1944 // Before reference types this byte was required to be a single zero
1945 // byte, not a LEB-encoded zero, so require a precise zero byte.
1946 match self.read_u8()? {
1947 0 => Ok(0),
1948 _ => bail!(self.original_position() - 1, "zero byte expected"),
1949 }
1950 }
1951 }
1952}
1953
1954// See documentation on `BinaryReader::features` for more on what's going on
1955// here.
1956macro_rules! define_feature_accessor {
1957 ($feature:ident = $default:expr) => {
1958 impl BinaryReader<'_> {
1959 #[inline]
1960 #[allow(dead_code)]
1961 pub(crate) fn $feature(&self) -> bool {
1962 #[cfg(feature = "features")]
1963 {
1964 self.features.$feature()
1965 }
1966 #[cfg(not(feature = "features"))]
1967 {
1968 true
1969 }
1970 }
1971 }
1972 };
1973}
1974
1975super::features::foreach_wasm_feature!(define_feature_accessor);
1976
1977impl<'a> BrTable<'a> {
1978 /// Returns the number of `br_table` entries, not including the default
1979 /// label
1980 pub fn len(&self) -> u32 {
1981 self.cnt
1982 }
1983
1984 /// Returns whether `BrTable` doesn't have any labels apart from the default one.
1985 pub fn is_empty(&self) -> bool {
1986 self.len() == 0
1987 }
1988
1989 /// Returns the default target of this `br_table` instruction.
1990 pub fn default(&self) -> u32 {
1991 self.default
1992 }
1993
1994 /// Returns the list of targets that this `br_table` instruction will be
1995 /// jumping to.
1996 ///
1997 /// This method will return an iterator which parses each target of this
1998 /// `br_table` except the default target. The returned iterator will
1999 /// yield `self.len()` elements.
2000 ///
2001 /// # Examples
2002 ///
2003 /// ```rust
2004 /// use wasmparser::{BinaryReader, Operator};
2005 ///
2006 /// let buf = [0x0e, 0x02, 0x01, 0x02, 0x00];
2007 /// let mut reader = BinaryReader::new(&buf, 0);
2008 /// let op = reader.read_operator().unwrap();
2009 /// if let Operator::BrTable { targets } = op {
2010 /// let targets = targets.targets().collect::<Result<Vec<_>, _>>().unwrap();
2011 /// assert_eq!(targets, [1, 2]);
2012 /// }
2013 /// ```
2014 pub fn targets(&self) -> BrTableTargets {
2015 BrTableTargets {
2016 reader: self.reader.clone(),
2017 remaining: self.cnt,
2018 }
2019 }
2020}
2021
2022/// An iterator over the targets of a [`BrTable`].
2023///
2024/// # Note
2025///
2026/// This iterator parses each target of the underlying `br_table`
2027/// except for the default target.
2028/// The iterator will yield exactly as many targets as the `br_table` has.
2029pub struct BrTableTargets<'a> {
2030 reader: crate::BinaryReader<'a>,
2031 remaining: u32,
2032}
2033
2034impl<'a> Iterator for BrTableTargets<'a> {
2035 type Item = Result<u32>;
2036
2037 fn size_hint(&self) -> (usize, Option<usize>) {
2038 let remaining: usize = usize::try_from(self.remaining).unwrap_or_else(|error: TryFromIntError| {
2039 panic!("could not convert remaining `u32` into `usize`: {}", error)
2040 });
2041 (remaining, Some(remaining))
2042 }
2043
2044 fn next(&mut self) -> Option<Self::Item> {
2045 if self.remaining == 0 {
2046 if !self.reader.eof() {
2047 return Some(Err(BinaryReaderError::new(
2048 message:"trailing data in br_table",
2049 self.reader.original_position(),
2050 )));
2051 }
2052 return None;
2053 }
2054 self.remaining -= 1;
2055 Some(self.reader.read_var_u32())
2056 }
2057}
2058
2059impl fmt::Debug for BrTable<'_> {
2060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2061 let mut f: DebugStruct<'_, '_> = f.debug_struct(name:"BrTable");
2062 f.field(name:"count", &self.cnt);
2063 f.field(name:"default", &self.default);
2064 match self.targets().collect::<Result<Vec<_>>>() {
2065 Ok(targets: Vec) => {
2066 f.field(name:"targets", &targets);
2067 }
2068 Err(_) => {
2069 f.field(name:"reader", &self.reader);
2070 }
2071 }
2072 f.finish()
2073 }
2074}
2075
2076/// A factory to construct [`Operator`] instances via the [`VisitOperator`] trait.
2077struct OperatorFactory<'a> {
2078 marker: core::marker::PhantomData<fn() -> &'a ()>,
2079}
2080
2081impl<'a> OperatorFactory<'a> {
2082 /// Creates a new [`OperatorFactory`].
2083 fn new() -> Self {
2084 Self {
2085 marker: core::marker::PhantomData,
2086 }
2087 }
2088}
2089
2090macro_rules! define_visit_operator {
2091 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
2092 $(
2093 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Operator<'a> {
2094 Operator::$op $({ $($arg),* })?
2095 }
2096 )*
2097 }
2098}
2099
2100impl<'a> VisitOperator<'a> for OperatorFactory<'a> {
2101 type Output = Operator<'a>;
2102
2103 for_each_operator!(define_visit_operator);
2104}
2105
2106/// Iterator returned from [`BinaryReader::read_iter`].
2107pub struct BinaryReaderIter<'a, 'me, T: FromReader<'a>> {
2108 remaining: usize,
2109 pub(crate) reader: &'me mut BinaryReader<'a>,
2110 _marker: marker::PhantomData<T>,
2111}
2112
2113impl<'a, T> Iterator for BinaryReaderIter<'a, '_, T>
2114where
2115 T: FromReader<'a>,
2116{
2117 type Item = Result<T>;
2118
2119 fn next(&mut self) -> Option<Result<T>> {
2120 if self.remaining == 0 {
2121 None
2122 } else {
2123 let ret: Result = self.reader.read::<T>();
2124 if ret.is_err() {
2125 self.remaining = 0;
2126 } else {
2127 self.remaining -= 1;
2128 }
2129 Some(ret)
2130 }
2131 }
2132
2133 fn size_hint(&self) -> (usize, Option<usize>) {
2134 (self.remaining, Some(self.remaining))
2135 }
2136}
2137
2138impl<'a, T> Drop for BinaryReaderIter<'a, '_, T>
2139where
2140 T: FromReader<'a>,
2141{
2142 fn drop(&mut self) {
2143 while self.next().is_some() {
2144 // ...
2145 }
2146 }
2147}
2148