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