Skip to main content

wasmparser/
binary_reader.rs

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