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