1 /* Copyright 2019 Mozilla Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 // The basic validation algorithm here is copied from the "Validation
17 // Algorithm" section of the WebAssembly specification -
18 // https://webassembly.github.io/spec/core/appendix/algorithm.html.
19 //
20 // That algorithm is followed pretty closely here, namely `push_operand`,
21 // `pop_operand`, `push_ctrl`, and `pop_ctrl`. If anything here is a bit
22 // confusing it's recomended to read over that section to see how it maps to
23 // the various methods here.
24 
25 use crate::limits::MAX_WASM_FUNCTION_LOCALS;
26 use crate::primitives::{MemoryImmediate, Operator, SIMDLaneIndex, Type, TypeOrFuncType};
27 use crate::{BinaryReaderError, Result, WasmFeatures, WasmFuncType, WasmModuleResources};
28 
29 /// A wrapper around a `BinaryReaderError` where the inner error's offset is a
30 /// temporary placeholder value. This can be converted into a proper
31 /// `BinaryReaderError` via the `set_offset` method, which replaces the
32 /// placeholder offset with an actual offset.
33 pub(crate) struct OperatorValidatorError(pub(crate) BinaryReaderError);
34 
35 /// Create an `OperatorValidatorError` with a format string.
36 macro_rules! format_op_err {
37     ( $( $arg:expr ),* $(,)* ) => {
38         OperatorValidatorError::new(format!( $( $arg ),* ))
39     }
40 }
41 
42 /// Early return an `Err(OperatorValidatorError)` with a format string.
43 macro_rules! bail_op_err {
44     ( $( $arg:expr ),* $(,)* ) => {
45         return Err(format_op_err!( $( $arg ),* ));
46     }
47 }
48 
49 impl OperatorValidatorError {
50     /// Create a new `OperatorValidatorError` with a placeholder offset.
new(message: impl Into<String>) -> Self51     pub(crate) fn new(message: impl Into<String>) -> Self {
52         let offset = std::usize::MAX;
53         let e = BinaryReaderError::new(message, offset);
54         OperatorValidatorError(e)
55     }
56 
57     /// Convert this `OperatorValidatorError` into a `BinaryReaderError` by
58     /// supplying an actual offset to replace the internal placeholder offset.
set_offset(mut self, offset: usize) -> BinaryReaderError59     pub(crate) fn set_offset(mut self, offset: usize) -> BinaryReaderError {
60         debug_assert_eq!(self.0.inner.offset, std::usize::MAX);
61         self.0.inner.offset = offset;
62         self.0
63     }
64 }
65 
66 type OperatorValidatorResult<T> = std::result::Result<T, OperatorValidatorError>;
67 
68 pub(crate) struct OperatorValidator {
69     // The total number of locals that this function contains
70     num_locals: u32,
71     // This is a "compressed" list of locals for this function. The list of
72     // locals are represented as a list of tuples. The second element is the
73     // type of the local, and the first element is monotonically increasing as
74     // you visit elements of this list. The first element is the maximum index
75     // of the local, after the previous index, of the type specified.
76     //
77     // This allows us to do a binary search on the list for a local's index for
78     // `local.{get,set,tee}`. We do a binary search for the index desired, and
79     // it either lies in a "hole" where the maximum index is specified later,
80     // or it's at the end of the list meaning it's out of bounds.
81     locals: Vec<(u32, Type)>,
82 
83     // The `operands` is the current type stack, and the `control` list is the
84     // list of blocks that we're currently in.
85     pub(crate) operands: Vec<Option<Type>>,
86     control: Vec<Frame>,
87 
88     // This is a list of flags for wasm features which are used to gate various
89     // instructions.
90     features: WasmFeatures,
91 }
92 
93 // This structure corresponds to `ctrl_frame` as specified at in the validation
94 // appendix of the wasm spec
95 struct Frame {
96     // Indicator for what kind of instruction pushed this frame.
97     kind: FrameKind,
98     // The type signature of this frame, represented as a singular return type
99     // or a type index pointing into the module's types.
100     block_type: TypeOrFuncType,
101     // The index, below which, this frame cannot modify the operand stack.
102     height: usize,
103     // Whether this frame is unreachable so far.
104     unreachable: bool,
105 }
106 
107 #[derive(PartialEq, Copy, Clone)]
108 enum FrameKind {
109     Block,
110     If,
111     Else,
112     Loop,
113     Try,
114     Catch,
115     CatchAll,
116     Unwind,
117 }
118 
119 impl OperatorValidator {
new( ty: u32, offset: usize, features: &WasmFeatures, resources: &impl WasmModuleResources, ) -> Result<OperatorValidator>120     pub fn new(
121         ty: u32,
122         offset: usize,
123         features: &WasmFeatures,
124         resources: &impl WasmModuleResources,
125     ) -> Result<OperatorValidator> {
126         let locals = func_type_at(resources, ty)
127             .map_err(|e| e.set_offset(offset))?
128             .inputs()
129             .enumerate()
130             .map(|(i, ty)| (i as u32, ty))
131             .collect::<Vec<_>>();
132         Ok(OperatorValidator {
133             num_locals: locals.len() as u32,
134             locals,
135             operands: Vec::new(),
136             control: vec![Frame {
137                 kind: FrameKind::Block,
138                 block_type: TypeOrFuncType::FuncType(ty),
139                 height: 0,
140                 unreachable: false,
141             }],
142             features: *features,
143         })
144     }
145 
define_locals(&mut self, offset: usize, count: u32, ty: Type) -> Result<()>146     pub fn define_locals(&mut self, offset: usize, count: u32, ty: Type) -> Result<()> {
147         self.features
148             .check_value_type(ty)
149             .map_err(|e| BinaryReaderError::new(e, offset))?;
150         if count == 0 {
151             return Ok(());
152         }
153         match self.num_locals.checked_add(count) {
154             Some(n) => self.num_locals = n,
155             None => return Err(BinaryReaderError::new("locals overflow", offset)),
156         }
157         if self.num_locals > (MAX_WASM_FUNCTION_LOCALS as u32) {
158             return Err(BinaryReaderError::new("locals exceed maximum", offset));
159         }
160         self.locals.push((self.num_locals - 1, ty));
161         Ok(())
162     }
163 
164     /// Fetches the type for the local at `idx`, returning an error if it's out
165     /// of bounds.
local(&self, idx: u32) -> OperatorValidatorResult<Type>166     fn local(&self, idx: u32) -> OperatorValidatorResult<Type> {
167         match self.locals.binary_search_by_key(&idx, |(idx, _)| *idx) {
168             // If this index would be inserted at the end of the list, then the
169             // index is out of bounds and we return an error.
170             Err(i) if i == self.locals.len() => {
171                 bail_op_err!("unknown local {}: local index out of bounds", idx)
172             }
173             // If `Ok` is returned we found the index exactly, or if `Err` is
174             // returned the position is the one which is the least index
175             // greater thatn `idx`, which is still the type of `idx` according
176             // to our "compressed" representation. In both cases we access the
177             // list at index `i`.
178             Ok(i) | Err(i) => Ok(self.locals[i].1),
179         }
180     }
181 
182     /// Pushes a type onto the operand stack.
183     ///
184     /// This is used by instructions to represent a value that is pushed to the
185     /// operand stack. This can fail, but only if `Type` is feature gated.
186     /// Otherwise the push operation always succeeds.
push_operand(&mut self, ty: Type) -> OperatorValidatorResult<()>187     fn push_operand(&mut self, ty: Type) -> OperatorValidatorResult<()> {
188         self.features
189             .check_value_type(ty)
190             .map_err(OperatorValidatorError::new)?;
191         self.operands.push(Some(ty));
192         Ok(())
193     }
194 
195     /// Attempts to pop a type from the operand stack.
196     ///
197     /// This function is used to remove types from the operand stack. The
198     /// `expected` argument can be used to indicate that a type is required, or
199     /// simply that something is needed to be popped.
200     ///
201     /// If `expected` is `Some(T)` then this will be guaranteed to return
202     /// `Some(T)`, and it will only return success if the current block is
203     /// unreachable or if `T` was found at the top of the operand stack.
204     ///
205     /// If `expected` is `None` then it indicates that something must be on the
206     /// operand stack, but it doesn't matter what's on the operand stack. This
207     /// is useful for polymorphic instructions like `select`.
208     ///
209     /// If `Some(T)` is returned then `T` was popped from the operand stack and
210     /// matches `expected`. If `None` is returned then it means that `None` was
211     /// expected and a type was successfully popped, but its exact type is
212     /// indeterminate because the current block is unreachable.
pop_operand(&mut self, expected: Option<Type>) -> OperatorValidatorResult<Option<Type>>213     fn pop_operand(&mut self, expected: Option<Type>) -> OperatorValidatorResult<Option<Type>> {
214         let control = self.control.last().unwrap();
215         let actual = if self.operands.len() == control.height {
216             if control.unreachable {
217                 None
218             } else {
219                 let desc = match expected {
220                     Some(ty) => ty_to_str(ty),
221                     None => "a type",
222                 };
223                 bail_op_err!("type mismatch: expected {} but nothing on stack", desc)
224             }
225         } else {
226             self.operands.pop().unwrap()
227         };
228         let actual_ty = match actual {
229             Some(ty) => ty,
230             None => return Ok(expected),
231         };
232         let expected_ty = match expected {
233             Some(ty) => ty,
234             None => return Ok(actual),
235         };
236         if actual_ty != expected_ty {
237             bail_op_err!(
238                 "type mismatch: expected {}, found {}",
239                 ty_to_str(expected_ty),
240                 ty_to_str(actual_ty)
241             )
242         } else {
243             Ok(actual)
244         }
245     }
246 
247     /// Flags the current control frame as unreachable, additionally truncating
248     /// the currently active operand stack.
unreachable(&mut self)249     fn unreachable(&mut self) {
250         let control = self.control.last_mut().unwrap();
251         self.operands.truncate(control.height);
252         control.unreachable = true;
253     }
254 
255     /// Pushes a new frame onto the control stack.
256     ///
257     /// This operation is used when entering a new block such as an if, loop,
258     /// or block itself. The `kind` of block is specified which indicates how
259     /// breaks interact with this block's type. Additionally the type signature
260     /// of the block is specified by `ty`.
push_ctrl( &mut self, kind: FrameKind, ty: TypeOrFuncType, resources: &impl WasmModuleResources, ) -> OperatorValidatorResult<()>261     fn push_ctrl(
262         &mut self,
263         kind: FrameKind,
264         ty: TypeOrFuncType,
265         resources: &impl WasmModuleResources,
266     ) -> OperatorValidatorResult<()> {
267         // Push a new frame which has a snapshot of the height of the current
268         // operand stack.
269         self.control.push(Frame {
270             kind,
271             block_type: ty,
272             height: self.operands.len(),
273             unreachable: false,
274         });
275         // All of the parameters are now also available in this control frame,
276         // so we push them here in order.
277         for ty in params(ty, resources)? {
278             self.push_operand(ty)?;
279         }
280         Ok(())
281     }
282 
283     /// Pops a frame from the control stack.
284     ///
285     /// This function is used when exiting a block and leaves a block scope.
286     /// Internally this will validate that blocks have the correct result type.
pop_ctrl(&mut self, resources: &impl WasmModuleResources) -> OperatorValidatorResult<Frame>287     fn pop_ctrl(&mut self, resources: &impl WasmModuleResources) -> OperatorValidatorResult<Frame> {
288         // Read the expected type and expected height of the operand stack the
289         // end of the frame.
290         let frame = self.control.last().unwrap();
291         // The end of an `unwind` should check against the empty block type.
292         let ty = if frame.kind == FrameKind::Unwind {
293             TypeOrFuncType::Type(Type::EmptyBlockType)
294         } else {
295             frame.block_type
296         };
297         let height = frame.height;
298 
299         // Pop all the result types, in reverse order, from the operand stack.
300         // These types will, possibly, be transferred to the next frame.
301         for ty in results(ty, resources)?.rev() {
302             self.pop_operand(Some(ty))?;
303         }
304 
305         // Make sure that the operand stack has returned to is original
306         // height...
307         if self.operands.len() != height {
308             bail_op_err!("type mismatch: values remaining on stack at end of block");
309         }
310 
311         // And then we can remove it!
312         Ok(self.control.pop().unwrap())
313     }
314 
315     /// Validates a relative jump to the `depth` specified.
316     ///
317     /// Returns the type signature of the block that we're jumping to as well
318     /// as the kind of block if the jump is valid. Otherwise returns an error.
jump(&self, depth: u32) -> OperatorValidatorResult<(TypeOrFuncType, FrameKind)>319     fn jump(&self, depth: u32) -> OperatorValidatorResult<(TypeOrFuncType, FrameKind)> {
320         match (self.control.len() - 1).checked_sub(depth as usize) {
321             Some(i) => {
322                 let frame = &self.control[i];
323                 Ok((frame.block_type, frame.kind))
324             }
325             None => bail_op_err!("unknown label: branch depth too large"),
326         }
327     }
328 
329     /// Validates that `memory_index` is valid in this module, and returns the
330     /// type of address used to index the memory specified.
check_memory_index( &self, memory_index: u32, resources: impl WasmModuleResources, ) -> OperatorValidatorResult<Type>331     fn check_memory_index(
332         &self,
333         memory_index: u32,
334         resources: impl WasmModuleResources,
335     ) -> OperatorValidatorResult<Type> {
336         if memory_index > 0 && !self.features.multi_memory {
337             return Err(OperatorValidatorError::new(
338                 "multi-memory support is not enabled",
339             ));
340         }
341         match resources.memory_at(memory_index) {
342             Some(mem) => Ok(mem.index_type()),
343             None => bail_op_err!("unknown memory {}", memory_index),
344         }
345     }
346 
347     /// Validates a `memarg for alignment and such (also the memory it
348     /// references), and returns the type of index used to address the memory.
check_memarg( &self, memarg: MemoryImmediate, max_align: u8, resources: impl WasmModuleResources, ) -> OperatorValidatorResult<Type>349     fn check_memarg(
350         &self,
351         memarg: MemoryImmediate,
352         max_align: u8,
353         resources: impl WasmModuleResources,
354     ) -> OperatorValidatorResult<Type> {
355         let index_ty = self.check_memory_index(memarg.memory, resources)?;
356         let align = memarg.align;
357         if align > max_align {
358             return Err(OperatorValidatorError::new(
359                 "alignment must not be larger than natural",
360             ));
361         }
362         Ok(index_ty)
363     }
364 
365     #[cfg(feature = "deterministic")]
check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()>366     fn check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()> {
367         if !self.features.deterministic_only {
368             return Err(OperatorValidatorError::new(
369                 "deterministic_only support is not enabled",
370             ));
371         }
372         Ok(())
373     }
374 
375     #[inline(always)]
376     #[cfg(not(feature = "deterministic"))]
check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()>377     fn check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()> {
378         Ok(())
379     }
380 
check_threads_enabled(&self) -> OperatorValidatorResult<()>381     fn check_threads_enabled(&self) -> OperatorValidatorResult<()> {
382         if !self.features.threads {
383             return Err(OperatorValidatorError::new(
384                 "threads support is not enabled",
385             ));
386         }
387         Ok(())
388     }
389 
check_reference_types_enabled(&self) -> OperatorValidatorResult<()>390     fn check_reference_types_enabled(&self) -> OperatorValidatorResult<()> {
391         if !self.features.reference_types {
392             return Err(OperatorValidatorError::new(
393                 "reference types support is not enabled",
394             ));
395         }
396         Ok(())
397     }
398 
check_simd_enabled(&self) -> OperatorValidatorResult<()>399     fn check_simd_enabled(&self) -> OperatorValidatorResult<()> {
400         if !self.features.simd {
401             return Err(OperatorValidatorError::new("SIMD support is not enabled"));
402         }
403         Ok(())
404     }
405 
check_exceptions_enabled(&self) -> OperatorValidatorResult<()>406     fn check_exceptions_enabled(&self) -> OperatorValidatorResult<()> {
407         if !self.features.exceptions {
408             return Err(OperatorValidatorError::new(
409                 "Exceptions support is not enabled",
410             ));
411         }
412         Ok(())
413     }
414 
check_bulk_memory_enabled(&self) -> OperatorValidatorResult<()>415     fn check_bulk_memory_enabled(&self) -> OperatorValidatorResult<()> {
416         if !self.features.bulk_memory {
417             return Err(OperatorValidatorError::new(
418                 "bulk memory support is not enabled",
419             ));
420         }
421         Ok(())
422     }
423 
check_shared_memarg_wo_align( &self, memarg: MemoryImmediate, resources: impl WasmModuleResources, ) -> OperatorValidatorResult<Type>424     fn check_shared_memarg_wo_align(
425         &self,
426         memarg: MemoryImmediate,
427         resources: impl WasmModuleResources,
428     ) -> OperatorValidatorResult<Type> {
429         self.check_memory_index(memarg.memory, resources)
430     }
431 
check_simd_lane_index(&self, index: SIMDLaneIndex, max: u8) -> OperatorValidatorResult<()>432     fn check_simd_lane_index(&self, index: SIMDLaneIndex, max: u8) -> OperatorValidatorResult<()> {
433         if index >= max {
434             return Err(OperatorValidatorError::new("SIMD index out of bounds"));
435         }
436         Ok(())
437     }
438 
439     /// Validates a block type, primarily with various in-flight proposals.
check_block_type( &self, ty: TypeOrFuncType, resources: impl WasmModuleResources, ) -> OperatorValidatorResult<()>440     fn check_block_type(
441         &self,
442         ty: TypeOrFuncType,
443         resources: impl WasmModuleResources,
444     ) -> OperatorValidatorResult<()> {
445         match ty {
446             TypeOrFuncType::Type(Type::EmptyBlockType)
447             | TypeOrFuncType::Type(Type::I32)
448             | TypeOrFuncType::Type(Type::I64)
449             | TypeOrFuncType::Type(Type::F32)
450             | TypeOrFuncType::Type(Type::F64) => Ok(()),
451             TypeOrFuncType::Type(Type::ExternRef) | TypeOrFuncType::Type(Type::FuncRef) => {
452                 self.check_reference_types_enabled()
453             }
454             TypeOrFuncType::Type(Type::V128) => self.check_simd_enabled(),
455             TypeOrFuncType::FuncType(idx) => {
456                 let ty = func_type_at(&resources, idx)?;
457                 if !self.features.multi_value {
458                     if ty.len_outputs() > 1 {
459                         return Err(OperatorValidatorError::new(
460                             "blocks, loops, and ifs may only return at most one \
461                              value when multi-value is not enabled",
462                         ));
463                     }
464                     if ty.len_inputs() > 0 {
465                         return Err(OperatorValidatorError::new(
466                             "blocks, loops, and ifs accept no parameters \
467                              when multi-value is not enabled",
468                         ));
469                     }
470                 }
471                 Ok(())
472             }
473             _ => Err(OperatorValidatorError::new("invalid block return type")),
474         }
475     }
476 
477     /// Validates a `call` instruction, ensuring that the function index is
478     /// in-bounds and the right types are on the stack to call the function.
check_call( &mut self, function_index: u32, resources: &impl WasmModuleResources, ) -> OperatorValidatorResult<()>479     fn check_call(
480         &mut self,
481         function_index: u32,
482         resources: &impl WasmModuleResources,
483     ) -> OperatorValidatorResult<()> {
484         let ty = match resources.type_of_function(function_index) {
485             Some(i) => i,
486             None => {
487                 bail_op_err!(
488                     "unknown function {}: function index out of bounds",
489                     function_index
490                 );
491             }
492         };
493         for ty in ty.inputs().rev() {
494             self.pop_operand(Some(ty))?;
495         }
496         for ty in ty.outputs() {
497             self.push_operand(ty)?;
498         }
499         Ok(())
500     }
501 
502     /// Validates a call to an indirect function, very similar to `check_call`.
check_call_indirect( &mut self, index: u32, table_index: u32, resources: &impl WasmModuleResources, ) -> OperatorValidatorResult<()>503     fn check_call_indirect(
504         &mut self,
505         index: u32,
506         table_index: u32,
507         resources: &impl WasmModuleResources,
508     ) -> OperatorValidatorResult<()> {
509         match resources.table_at(table_index) {
510             None => {
511                 return Err(OperatorValidatorError::new(
512                     "unknown table: table index out of bounds",
513                 ));
514             }
515             Some(tab) => {
516                 if tab.element_type != Type::FuncRef {
517                     return Err(OperatorValidatorError::new(
518                         "indirect calls must go through a table of funcref",
519                     ));
520                 }
521             }
522         }
523         let ty = func_type_at(&resources, index)?;
524         self.pop_operand(Some(Type::I32))?;
525         for ty in ty.inputs().rev() {
526             self.pop_operand(Some(ty))?;
527         }
528         for ty in ty.outputs() {
529             self.push_operand(ty)?;
530         }
531         Ok(())
532     }
533 
534     /// Validates a `return` instruction, popping types from the operand
535     /// stack that the function needs.
check_return( &mut self, resources: &impl WasmModuleResources, ) -> OperatorValidatorResult<()>536     fn check_return(
537         &mut self,
538         resources: &impl WasmModuleResources,
539     ) -> OperatorValidatorResult<()> {
540         for ty in results(self.control[0].block_type, resources)?.rev() {
541             self.pop_operand(Some(ty))?;
542         }
543         self.unreachable();
544         Ok(())
545     }
546 
process_operator( &mut self, operator: &Operator, resources: &impl WasmModuleResources, ) -> OperatorValidatorResult<()>547     pub fn process_operator(
548         &mut self,
549         operator: &Operator,
550         resources: &impl WasmModuleResources,
551     ) -> OperatorValidatorResult<()> {
552         if self.control.len() == 0 {
553             bail_op_err!("operators remaining after end of function");
554         }
555         match *operator {
556             Operator::Nop => {}
557 
558             // Note that the handling of these control flow operators are the
559             // same as specified in the "Validation Algorithm" appendix of the
560             // online wasm specification (referenced at the top of this module).
561             Operator::Unreachable => self.unreachable(),
562             Operator::Block { ty } => {
563                 self.check_block_type(ty, resources)?;
564                 for ty in params(ty, resources)?.rev() {
565                     self.pop_operand(Some(ty))?;
566                 }
567                 self.push_ctrl(FrameKind::Block, ty, resources)?;
568             }
569             Operator::Loop { ty } => {
570                 self.check_block_type(ty, resources)?;
571                 for ty in params(ty, resources)?.rev() {
572                     self.pop_operand(Some(ty))?;
573                 }
574                 self.push_ctrl(FrameKind::Loop, ty, resources)?;
575             }
576             Operator::If { ty } => {
577                 self.check_block_type(ty, resources)?;
578                 self.pop_operand(Some(Type::I32))?;
579                 for ty in params(ty, resources)?.rev() {
580                     self.pop_operand(Some(ty))?;
581                 }
582                 self.push_ctrl(FrameKind::If, ty, resources)?;
583             }
584             Operator::Else => {
585                 let frame = self.pop_ctrl(resources)?;
586                 if frame.kind != FrameKind::If {
587                     bail_op_err!("else found outside of an `if` block");
588                 }
589                 self.push_ctrl(FrameKind::Else, frame.block_type, resources)?
590             }
591             Operator::Try { ty } => {
592                 self.check_exceptions_enabled()?;
593                 self.check_block_type(ty, resources)?;
594                 for ty in params(ty, resources)?.rev() {
595                     self.pop_operand(Some(ty))?;
596                 }
597                 self.push_ctrl(FrameKind::Try, ty, resources)?;
598             }
599             Operator::Catch { index } => {
600                 self.check_exceptions_enabled()?;
601                 let frame = self.pop_ctrl(resources)?;
602                 if frame.kind != FrameKind::Try && frame.kind != FrameKind::Catch {
603                     bail_op_err!("catch found outside of an `try` block");
604                 }
605                 // Start a new frame and push `exnref` value.
606                 self.control.push(Frame {
607                     kind: FrameKind::Catch,
608                     block_type: frame.block_type,
609                     height: self.operands.len(),
610                     unreachable: false,
611                 });
612                 // Push exception argument types.
613                 let ty = event_at(&resources, index)?;
614                 for ty in ty.inputs() {
615                     self.push_operand(ty)?;
616                 }
617             }
618             Operator::Throw { index } => {
619                 self.check_exceptions_enabled()?;
620                 // Check values associated with the exception.
621                 let ty = event_at(&resources, index)?;
622                 for ty in ty.inputs().rev() {
623                     self.pop_operand(Some(ty))?;
624                 }
625                 if ty.outputs().len() > 0 {
626                     bail_op_err!("result type expected to be empty for exception");
627                 }
628                 self.unreachable();
629             }
630             Operator::Rethrow { relative_depth } => {
631                 self.check_exceptions_enabled()?;
632                 // This is not a jump, but we need to check that the `rethrow`
633                 // targets an actual `catch` to get the exception.
634                 let (_, kind) = self.jump(relative_depth)?;
635                 if kind != FrameKind::Catch && kind != FrameKind::CatchAll {
636                     bail_op_err!("rethrow target was not a `catch` block");
637                 }
638                 self.unreachable();
639             }
640             Operator::Unwind => {
641                 self.check_exceptions_enabled()?;
642                 // Switch from `try` to an `unwind` frame.
643                 let frame = self.pop_ctrl(resources)?;
644                 if frame.kind != FrameKind::Try {
645                     bail_op_err!("unwind found outside of an `try` block");
646                 }
647                 self.control.push(Frame {
648                     kind: FrameKind::Unwind,
649                     block_type: frame.block_type,
650                     height: self.operands.len(),
651                     unreachable: false,
652                 });
653             }
654             Operator::Delegate { relative_depth } => {
655                 self.check_exceptions_enabled()?;
656                 let frame = self.pop_ctrl(resources)?;
657                 if frame.kind != FrameKind::Try {
658                     bail_op_err!("delegate found outside of an `try` block");
659                 }
660                 // This operation is not a jump, but we need to check the
661                 // depth for validity and that it targets a `try`.
662                 let (_, kind) = self.jump(relative_depth)?;
663                 if kind != FrameKind::Try
664                     && (kind != FrameKind::Block
665                         || self.control.len() != relative_depth as usize + 1)
666                 {
667                     bail_op_err!("must delegate to a try block or caller");
668                 }
669                 for ty in results(frame.block_type, resources)? {
670                     self.push_operand(ty)?;
671                 }
672             }
673             Operator::CatchAll => {
674                 self.check_exceptions_enabled()?;
675                 let frame = self.pop_ctrl(resources)?;
676                 if frame.kind == FrameKind::CatchAll {
677                     bail_op_err!("only one catch_all allowed per `try` block");
678                 } else if frame.kind != FrameKind::Try && frame.kind != FrameKind::Catch {
679                     bail_op_err!("catch_all found outside of a `try` block");
680                 }
681                 self.control.push(Frame {
682                     kind: FrameKind::CatchAll,
683                     block_type: frame.block_type,
684                     height: self.operands.len(),
685                     unreachable: false,
686                 });
687             }
688             Operator::End => {
689                 let mut frame = self.pop_ctrl(resources)?;
690 
691                 // Note that this `if` isn't included in the appendix right
692                 // now, but it's used to allow for `if` statements that are
693                 // missing an `else` block which have the same parameter/return
694                 // types on the block (since that's valid).
695                 match frame.kind {
696                     FrameKind::If => {
697                         self.push_ctrl(FrameKind::Else, frame.block_type, resources)?;
698                         frame = self.pop_ctrl(resources)?;
699                     }
700                     FrameKind::Try => {
701                         bail_op_err!("expected catch block");
702                     }
703                     _ => (),
704                 }
705 
706                 for ty in results(frame.block_type, resources)? {
707                     self.push_operand(ty)?;
708                 }
709             }
710             Operator::Br { relative_depth } => {
711                 let (ty, kind) = self.jump(relative_depth)?;
712                 for ty in label_types(ty, resources, kind)?.rev() {
713                     self.pop_operand(Some(ty))?;
714                 }
715                 self.unreachable();
716             }
717             Operator::BrIf { relative_depth } => {
718                 self.pop_operand(Some(Type::I32))?;
719                 let (ty, kind) = self.jump(relative_depth)?;
720                 for ty in label_types(ty, resources, kind)?.rev() {
721                     self.pop_operand(Some(ty))?;
722                 }
723                 for ty in label_types(ty, resources, kind)? {
724                     self.push_operand(ty)?;
725                 }
726             }
727             Operator::BrTable { ref table } => {
728                 self.pop_operand(Some(Type::I32))?;
729                 let mut label = None;
730                 for element in table.targets() {
731                     let (relative_depth, _is_default) = element.map_err(|mut e| {
732                         e.inner.offset = usize::max_value();
733                         OperatorValidatorError(e)
734                     })?;
735                     let block = self.jump(relative_depth)?;
736                     match label {
737                         None => label = Some(block),
738                         Some(prev) => {
739                             let a = label_types(block.0, resources, block.1)?;
740                             let b = label_types(prev.0, resources, prev.1)?;
741                             if a.ne(b) {
742                                 bail_op_err!(
743                                     "type mismatch: br_table target labels have different types"
744                                 );
745                             }
746                         }
747                     }
748                 }
749                 let (ty, kind) = label.unwrap();
750                 for ty in label_types(ty, resources, kind)?.rev() {
751                     self.pop_operand(Some(ty))?;
752                 }
753                 self.unreachable();
754             }
755             Operator::Return => self.check_return(resources)?,
756             Operator::Call { function_index } => self.check_call(function_index, resources)?,
757             Operator::ReturnCall { function_index } => {
758                 if !self.features.tail_call {
759                     return Err(OperatorValidatorError::new(
760                         "tail calls support is not enabled",
761                     ));
762                 }
763                 self.check_call(function_index, resources)?;
764                 self.check_return(resources)?;
765             }
766             Operator::CallIndirect { index, table_index } => {
767                 self.check_call_indirect(index, table_index, resources)?
768             }
769             Operator::ReturnCallIndirect { index, table_index } => {
770                 if !self.features.tail_call {
771                     return Err(OperatorValidatorError::new(
772                         "tail calls support is not enabled",
773                     ));
774                 }
775                 self.check_call_indirect(index, table_index, resources)?;
776                 self.check_return(resources)?;
777             }
778             Operator::Drop => {
779                 self.pop_operand(None)?;
780             }
781             Operator::Select => {
782                 self.pop_operand(Some(Type::I32))?;
783                 let ty = self.pop_operand(None)?;
784                 match self.pop_operand(ty)? {
785                     ty @ Some(Type::I32)
786                     | ty @ Some(Type::I64)
787                     | ty @ Some(Type::F32)
788                     | ty @ Some(Type::F64) => self.operands.push(ty),
789                     ty @ Some(Type::V128) => {
790                         self.check_simd_enabled()?;
791                         self.operands.push(ty)
792                     }
793                     None => self.operands.push(None),
794                     Some(_) => bail_op_err!("type mismatch: select only takes integral types"),
795                 }
796             }
797             Operator::TypedSelect { ty } => {
798                 self.pop_operand(Some(Type::I32))?;
799                 self.pop_operand(Some(ty))?;
800                 self.pop_operand(Some(ty))?;
801                 self.push_operand(ty)?;
802             }
803             Operator::LocalGet { local_index } => {
804                 let ty = self.local(local_index)?;
805                 self.push_operand(ty)?;
806             }
807             Operator::LocalSet { local_index } => {
808                 let ty = self.local(local_index)?;
809                 self.pop_operand(Some(ty))?;
810             }
811             Operator::LocalTee { local_index } => {
812                 let ty = self.local(local_index)?;
813                 self.pop_operand(Some(ty))?;
814                 self.push_operand(ty)?;
815             }
816             Operator::GlobalGet { global_index } => {
817                 if let Some(ty) = resources.global_at(global_index) {
818                     self.push_operand(ty.content_type)?;
819                 } else {
820                     return Err(OperatorValidatorError::new(
821                         "unknown global: global index out of bounds",
822                     ));
823                 };
824             }
825             Operator::GlobalSet { global_index } => {
826                 if let Some(ty) = resources.global_at(global_index) {
827                     if !ty.mutable {
828                         return Err(OperatorValidatorError::new(
829                             "global is immutable: cannot modify it with `global.set`",
830                         ));
831                     }
832                     self.pop_operand(Some(ty.content_type))?;
833                 } else {
834                     return Err(OperatorValidatorError::new(
835                         "unknown global: global index out of bounds",
836                     ));
837                 };
838             }
839             Operator::I32Load { memarg } => {
840                 let ty = self.check_memarg(memarg, 2, resources)?;
841                 self.pop_operand(Some(ty))?;
842                 self.push_operand(Type::I32)?;
843             }
844             Operator::I64Load { memarg } => {
845                 let ty = self.check_memarg(memarg, 3, resources)?;
846                 self.pop_operand(Some(ty))?;
847                 self.push_operand(Type::I64)?;
848             }
849             Operator::F32Load { memarg } => {
850                 self.check_non_deterministic_enabled()?;
851                 let ty = self.check_memarg(memarg, 2, resources)?;
852                 self.pop_operand(Some(ty))?;
853                 self.push_operand(Type::F32)?;
854             }
855             Operator::F64Load { memarg } => {
856                 self.check_non_deterministic_enabled()?;
857                 let ty = self.check_memarg(memarg, 3, resources)?;
858                 self.pop_operand(Some(ty))?;
859                 self.push_operand(Type::F64)?;
860             }
861             Operator::I32Load8S { memarg } | Operator::I32Load8U { memarg } => {
862                 let ty = self.check_memarg(memarg, 0, resources)?;
863                 self.pop_operand(Some(ty))?;
864                 self.push_operand(Type::I32)?;
865             }
866             Operator::I32Load16S { memarg } | Operator::I32Load16U { memarg } => {
867                 let ty = self.check_memarg(memarg, 1, resources)?;
868                 self.pop_operand(Some(ty))?;
869                 self.push_operand(Type::I32)?;
870             }
871             Operator::I64Load8S { memarg } | Operator::I64Load8U { memarg } => {
872                 let ty = self.check_memarg(memarg, 0, resources)?;
873                 self.pop_operand(Some(ty))?;
874                 self.push_operand(Type::I64)?;
875             }
876             Operator::I64Load16S { memarg } | Operator::I64Load16U { memarg } => {
877                 let ty = self.check_memarg(memarg, 1, resources)?;
878                 self.pop_operand(Some(ty))?;
879                 self.push_operand(Type::I64)?;
880             }
881             Operator::I64Load32S { memarg } | Operator::I64Load32U { memarg } => {
882                 let ty = self.check_memarg(memarg, 2, resources)?;
883                 self.pop_operand(Some(ty))?;
884                 self.push_operand(Type::I64)?;
885             }
886             Operator::I32Store { memarg } => {
887                 let ty = self.check_memarg(memarg, 2, resources)?;
888                 self.pop_operand(Some(Type::I32))?;
889                 self.pop_operand(Some(ty))?;
890             }
891             Operator::I64Store { memarg } => {
892                 let ty = self.check_memarg(memarg, 3, resources)?;
893                 self.pop_operand(Some(Type::I64))?;
894                 self.pop_operand(Some(ty))?;
895             }
896             Operator::F32Store { memarg } => {
897                 self.check_non_deterministic_enabled()?;
898                 let ty = self.check_memarg(memarg, 2, resources)?;
899                 self.pop_operand(Some(Type::F32))?;
900                 self.pop_operand(Some(ty))?;
901             }
902             Operator::F64Store { memarg } => {
903                 self.check_non_deterministic_enabled()?;
904                 let ty = self.check_memarg(memarg, 3, resources)?;
905                 self.pop_operand(Some(Type::F64))?;
906                 self.pop_operand(Some(ty))?;
907             }
908             Operator::I32Store8 { memarg } => {
909                 let ty = self.check_memarg(memarg, 0, resources)?;
910                 self.pop_operand(Some(Type::I32))?;
911                 self.pop_operand(Some(ty))?;
912             }
913             Operator::I32Store16 { memarg } => {
914                 let ty = self.check_memarg(memarg, 1, resources)?;
915                 self.pop_operand(Some(Type::I32))?;
916                 self.pop_operand(Some(ty))?;
917             }
918             Operator::I64Store8 { memarg } => {
919                 let ty = self.check_memarg(memarg, 0, resources)?;
920                 self.pop_operand(Some(Type::I64))?;
921                 self.pop_operand(Some(ty))?;
922             }
923             Operator::I64Store16 { memarg } => {
924                 let ty = self.check_memarg(memarg, 1, resources)?;
925                 self.pop_operand(Some(Type::I64))?;
926                 self.pop_operand(Some(ty))?;
927             }
928             Operator::I64Store32 { memarg } => {
929                 let ty = self.check_memarg(memarg, 2, resources)?;
930                 self.pop_operand(Some(Type::I64))?;
931                 self.pop_operand(Some(ty))?;
932             }
933             Operator::MemorySize { mem, mem_byte } => {
934                 if mem_byte != 0 && !self.features.multi_memory {
935                     return Err(OperatorValidatorError::new("multi-memory not enabled"));
936                 }
937                 let index_ty = self.check_memory_index(mem, resources)?;
938                 self.push_operand(index_ty)?;
939             }
940             Operator::MemoryGrow { mem, mem_byte } => {
941                 if mem_byte != 0 && !self.features.multi_memory {
942                     return Err(OperatorValidatorError::new("multi-memory not enabled"));
943                 }
944                 let index_ty = self.check_memory_index(mem, resources)?;
945                 self.pop_operand(Some(index_ty))?;
946                 self.push_operand(index_ty)?;
947             }
948             Operator::I32Const { .. } => self.push_operand(Type::I32)?,
949             Operator::I64Const { .. } => self.push_operand(Type::I64)?,
950             Operator::F32Const { .. } => {
951                 self.check_non_deterministic_enabled()?;
952                 self.push_operand(Type::F32)?;
953             }
954             Operator::F64Const { .. } => {
955                 self.check_non_deterministic_enabled()?;
956                 self.push_operand(Type::F64)?;
957             }
958             Operator::I32Eqz => {
959                 self.pop_operand(Some(Type::I32))?;
960                 self.push_operand(Type::I32)?;
961             }
962             Operator::I32Eq
963             | Operator::I32Ne
964             | Operator::I32LtS
965             | Operator::I32LtU
966             | Operator::I32GtS
967             | Operator::I32GtU
968             | Operator::I32LeS
969             | Operator::I32LeU
970             | Operator::I32GeS
971             | Operator::I32GeU => {
972                 self.pop_operand(Some(Type::I32))?;
973                 self.pop_operand(Some(Type::I32))?;
974                 self.push_operand(Type::I32)?;
975             }
976             Operator::I64Eqz => {
977                 self.pop_operand(Some(Type::I64))?;
978                 self.push_operand(Type::I32)?;
979             }
980             Operator::I64Eq
981             | Operator::I64Ne
982             | Operator::I64LtS
983             | Operator::I64LtU
984             | Operator::I64GtS
985             | Operator::I64GtU
986             | Operator::I64LeS
987             | Operator::I64LeU
988             | Operator::I64GeS
989             | Operator::I64GeU => {
990                 self.pop_operand(Some(Type::I64))?;
991                 self.pop_operand(Some(Type::I64))?;
992                 self.push_operand(Type::I32)?;
993             }
994             Operator::F32Eq
995             | Operator::F32Ne
996             | Operator::F32Lt
997             | Operator::F32Gt
998             | Operator::F32Le
999             | Operator::F32Ge => {
1000                 self.check_non_deterministic_enabled()?;
1001                 self.pop_operand(Some(Type::F32))?;
1002                 self.pop_operand(Some(Type::F32))?;
1003                 self.push_operand(Type::I32)?;
1004             }
1005             Operator::F64Eq
1006             | Operator::F64Ne
1007             | Operator::F64Lt
1008             | Operator::F64Gt
1009             | Operator::F64Le
1010             | Operator::F64Ge => {
1011                 self.check_non_deterministic_enabled()?;
1012                 self.pop_operand(Some(Type::F64))?;
1013                 self.pop_operand(Some(Type::F64))?;
1014                 self.push_operand(Type::I32)?;
1015             }
1016             Operator::I32Clz | Operator::I32Ctz | Operator::I32Popcnt => {
1017                 self.pop_operand(Some(Type::I32))?;
1018                 self.push_operand(Type::I32)?;
1019             }
1020             Operator::I32Add
1021             | Operator::I32Sub
1022             | Operator::I32Mul
1023             | Operator::I32DivS
1024             | Operator::I32DivU
1025             | Operator::I32RemS
1026             | Operator::I32RemU
1027             | Operator::I32And
1028             | Operator::I32Or
1029             | Operator::I32Xor
1030             | Operator::I32Shl
1031             | Operator::I32ShrS
1032             | Operator::I32ShrU
1033             | Operator::I32Rotl
1034             | Operator::I32Rotr => {
1035                 self.pop_operand(Some(Type::I32))?;
1036                 self.pop_operand(Some(Type::I32))?;
1037                 self.push_operand(Type::I32)?;
1038             }
1039             Operator::I64Clz | Operator::I64Ctz | Operator::I64Popcnt => {
1040                 self.pop_operand(Some(Type::I64))?;
1041                 self.push_operand(Type::I64)?;
1042             }
1043             Operator::I64Add
1044             | Operator::I64Sub
1045             | Operator::I64Mul
1046             | Operator::I64DivS
1047             | Operator::I64DivU
1048             | Operator::I64RemS
1049             | Operator::I64RemU
1050             | Operator::I64And
1051             | Operator::I64Or
1052             | Operator::I64Xor
1053             | Operator::I64Shl
1054             | Operator::I64ShrS
1055             | Operator::I64ShrU
1056             | Operator::I64Rotl
1057             | Operator::I64Rotr => {
1058                 self.pop_operand(Some(Type::I64))?;
1059                 self.pop_operand(Some(Type::I64))?;
1060                 self.push_operand(Type::I64)?;
1061             }
1062             Operator::F32Abs
1063             | Operator::F32Neg
1064             | Operator::F32Ceil
1065             | Operator::F32Floor
1066             | Operator::F32Trunc
1067             | Operator::F32Nearest
1068             | Operator::F32Sqrt => {
1069                 self.check_non_deterministic_enabled()?;
1070                 self.pop_operand(Some(Type::F32))?;
1071                 self.push_operand(Type::F32)?;
1072             }
1073             Operator::F32Add
1074             | Operator::F32Sub
1075             | Operator::F32Mul
1076             | Operator::F32Div
1077             | Operator::F32Min
1078             | Operator::F32Max
1079             | Operator::F32Copysign => {
1080                 self.check_non_deterministic_enabled()?;
1081                 self.pop_operand(Some(Type::F32))?;
1082                 self.pop_operand(Some(Type::F32))?;
1083                 self.push_operand(Type::F32)?;
1084             }
1085             Operator::F64Abs
1086             | Operator::F64Neg
1087             | Operator::F64Ceil
1088             | Operator::F64Floor
1089             | Operator::F64Trunc
1090             | Operator::F64Nearest
1091             | Operator::F64Sqrt => {
1092                 self.check_non_deterministic_enabled()?;
1093                 self.pop_operand(Some(Type::F64))?;
1094                 self.push_operand(Type::F64)?;
1095             }
1096             Operator::F64Add
1097             | Operator::F64Sub
1098             | Operator::F64Mul
1099             | Operator::F64Div
1100             | Operator::F64Min
1101             | Operator::F64Max
1102             | Operator::F64Copysign => {
1103                 self.check_non_deterministic_enabled()?;
1104                 self.pop_operand(Some(Type::F64))?;
1105                 self.pop_operand(Some(Type::F64))?;
1106                 self.push_operand(Type::F64)?;
1107             }
1108             Operator::I32WrapI64 => {
1109                 self.pop_operand(Some(Type::I64))?;
1110                 self.push_operand(Type::I32)?;
1111             }
1112             Operator::I32TruncF32S | Operator::I32TruncF32U => {
1113                 self.pop_operand(Some(Type::F32))?;
1114                 self.push_operand(Type::I32)?;
1115             }
1116             Operator::I32TruncF64S | Operator::I32TruncF64U => {
1117                 self.pop_operand(Some(Type::F64))?;
1118                 self.push_operand(Type::I32)?;
1119             }
1120             Operator::I64ExtendI32S | Operator::I64ExtendI32U => {
1121                 self.pop_operand(Some(Type::I32))?;
1122                 self.push_operand(Type::I64)?;
1123             }
1124             Operator::I64TruncF32S | Operator::I64TruncF32U => {
1125                 self.pop_operand(Some(Type::F32))?;
1126                 self.push_operand(Type::I64)?;
1127             }
1128             Operator::I64TruncF64S | Operator::I64TruncF64U => {
1129                 self.pop_operand(Some(Type::F64))?;
1130                 self.push_operand(Type::I64)?;
1131             }
1132             Operator::F32ConvertI32S | Operator::F32ConvertI32U => {
1133                 self.check_non_deterministic_enabled()?;
1134                 self.pop_operand(Some(Type::I32))?;
1135                 self.push_operand(Type::F32)?;
1136             }
1137             Operator::F32ConvertI64S | Operator::F32ConvertI64U => {
1138                 self.check_non_deterministic_enabled()?;
1139                 self.pop_operand(Some(Type::I64))?;
1140                 self.push_operand(Type::F32)?;
1141             }
1142             Operator::F32DemoteF64 => {
1143                 self.check_non_deterministic_enabled()?;
1144                 self.pop_operand(Some(Type::F64))?;
1145                 self.push_operand(Type::F32)?;
1146             }
1147             Operator::F64ConvertI32S | Operator::F64ConvertI32U => {
1148                 self.check_non_deterministic_enabled()?;
1149                 self.pop_operand(Some(Type::I32))?;
1150                 self.push_operand(Type::F64)?;
1151             }
1152             Operator::F64ConvertI64S | Operator::F64ConvertI64U => {
1153                 self.check_non_deterministic_enabled()?;
1154                 self.pop_operand(Some(Type::I64))?;
1155                 self.push_operand(Type::F64)?;
1156             }
1157             Operator::F64PromoteF32 => {
1158                 self.check_non_deterministic_enabled()?;
1159                 self.pop_operand(Some(Type::F32))?;
1160                 self.push_operand(Type::F64)?;
1161             }
1162             Operator::I32ReinterpretF32 => {
1163                 self.pop_operand(Some(Type::F32))?;
1164                 self.push_operand(Type::I32)?;
1165             }
1166             Operator::I64ReinterpretF64 => {
1167                 self.pop_operand(Some(Type::F64))?;
1168                 self.push_operand(Type::I64)?;
1169             }
1170             Operator::F32ReinterpretI32 => {
1171                 self.check_non_deterministic_enabled()?;
1172                 self.pop_operand(Some(Type::I32))?;
1173                 self.push_operand(Type::F32)?;
1174             }
1175             Operator::F64ReinterpretI64 => {
1176                 self.check_non_deterministic_enabled()?;
1177                 self.pop_operand(Some(Type::I64))?;
1178                 self.push_operand(Type::F64)?;
1179             }
1180             Operator::I32TruncSatF32S | Operator::I32TruncSatF32U => {
1181                 self.pop_operand(Some(Type::F32))?;
1182                 self.push_operand(Type::I32)?;
1183             }
1184             Operator::I32TruncSatF64S | Operator::I32TruncSatF64U => {
1185                 self.pop_operand(Some(Type::F64))?;
1186                 self.push_operand(Type::I32)?;
1187             }
1188             Operator::I64TruncSatF32S | Operator::I64TruncSatF32U => {
1189                 self.pop_operand(Some(Type::F32))?;
1190                 self.push_operand(Type::I64)?;
1191             }
1192             Operator::I64TruncSatF64S | Operator::I64TruncSatF64U => {
1193                 self.pop_operand(Some(Type::F64))?;
1194                 self.push_operand(Type::I64)?;
1195             }
1196             Operator::I32Extend16S | Operator::I32Extend8S => {
1197                 self.pop_operand(Some(Type::I32))?;
1198                 self.push_operand(Type::I32)?;
1199             }
1200 
1201             Operator::I64Extend32S | Operator::I64Extend16S | Operator::I64Extend8S => {
1202                 self.pop_operand(Some(Type::I64))?;
1203                 self.push_operand(Type::I64)?;
1204             }
1205 
1206             Operator::I32AtomicLoad { memarg }
1207             | Operator::I32AtomicLoad16U { memarg }
1208             | Operator::I32AtomicLoad8U { memarg } => {
1209                 self.check_threads_enabled()?;
1210                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1211                 self.pop_operand(Some(ty))?;
1212                 self.push_operand(Type::I32)?;
1213             }
1214             Operator::I64AtomicLoad { memarg }
1215             | Operator::I64AtomicLoad32U { memarg }
1216             | Operator::I64AtomicLoad16U { memarg }
1217             | Operator::I64AtomicLoad8U { memarg } => {
1218                 self.check_threads_enabled()?;
1219                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1220                 self.pop_operand(Some(ty))?;
1221                 self.push_operand(Type::I64)?;
1222             }
1223             Operator::I32AtomicStore { memarg }
1224             | Operator::I32AtomicStore16 { memarg }
1225             | Operator::I32AtomicStore8 { memarg } => {
1226                 self.check_threads_enabled()?;
1227                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1228                 self.pop_operand(Some(Type::I32))?;
1229                 self.pop_operand(Some(ty))?;
1230             }
1231             Operator::I64AtomicStore { memarg }
1232             | Operator::I64AtomicStore32 { memarg }
1233             | Operator::I64AtomicStore16 { memarg }
1234             | Operator::I64AtomicStore8 { memarg } => {
1235                 self.check_threads_enabled()?;
1236                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1237                 self.pop_operand(Some(Type::I64))?;
1238                 self.pop_operand(Some(ty))?;
1239             }
1240             Operator::I32AtomicRmwAdd { memarg }
1241             | Operator::I32AtomicRmwSub { memarg }
1242             | Operator::I32AtomicRmwAnd { memarg }
1243             | Operator::I32AtomicRmwOr { memarg }
1244             | Operator::I32AtomicRmwXor { memarg }
1245             | Operator::I32AtomicRmw16AddU { memarg }
1246             | Operator::I32AtomicRmw16SubU { memarg }
1247             | Operator::I32AtomicRmw16AndU { memarg }
1248             | Operator::I32AtomicRmw16OrU { memarg }
1249             | Operator::I32AtomicRmw16XorU { memarg }
1250             | Operator::I32AtomicRmw8AddU { memarg }
1251             | Operator::I32AtomicRmw8SubU { memarg }
1252             | Operator::I32AtomicRmw8AndU { memarg }
1253             | Operator::I32AtomicRmw8OrU { memarg }
1254             | Operator::I32AtomicRmw8XorU { memarg } => {
1255                 self.check_threads_enabled()?;
1256                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1257                 self.pop_operand(Some(Type::I32))?;
1258                 self.pop_operand(Some(ty))?;
1259                 self.push_operand(Type::I32)?;
1260             }
1261             Operator::I64AtomicRmwAdd { memarg }
1262             | Operator::I64AtomicRmwSub { memarg }
1263             | Operator::I64AtomicRmwAnd { memarg }
1264             | Operator::I64AtomicRmwOr { memarg }
1265             | Operator::I64AtomicRmwXor { memarg }
1266             | Operator::I64AtomicRmw32AddU { memarg }
1267             | Operator::I64AtomicRmw32SubU { memarg }
1268             | Operator::I64AtomicRmw32AndU { memarg }
1269             | Operator::I64AtomicRmw32OrU { memarg }
1270             | Operator::I64AtomicRmw32XorU { memarg }
1271             | Operator::I64AtomicRmw16AddU { memarg }
1272             | Operator::I64AtomicRmw16SubU { memarg }
1273             | Operator::I64AtomicRmw16AndU { memarg }
1274             | Operator::I64AtomicRmw16OrU { memarg }
1275             | Operator::I64AtomicRmw16XorU { memarg }
1276             | Operator::I64AtomicRmw8AddU { memarg }
1277             | Operator::I64AtomicRmw8SubU { memarg }
1278             | Operator::I64AtomicRmw8AndU { memarg }
1279             | Operator::I64AtomicRmw8OrU { memarg }
1280             | Operator::I64AtomicRmw8XorU { memarg } => {
1281                 self.check_threads_enabled()?;
1282                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1283                 self.pop_operand(Some(Type::I64))?;
1284                 self.pop_operand(Some(ty))?;
1285                 self.push_operand(Type::I64)?;
1286             }
1287             Operator::I32AtomicRmwXchg { memarg }
1288             | Operator::I32AtomicRmw16XchgU { memarg }
1289             | Operator::I32AtomicRmw8XchgU { memarg } => {
1290                 self.check_threads_enabled()?;
1291                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1292                 self.pop_operand(Some(Type::I32))?;
1293                 self.pop_operand(Some(ty))?;
1294                 self.push_operand(Type::I32)?;
1295             }
1296             Operator::I32AtomicRmwCmpxchg { memarg }
1297             | Operator::I32AtomicRmw16CmpxchgU { memarg }
1298             | Operator::I32AtomicRmw8CmpxchgU { memarg } => {
1299                 self.check_threads_enabled()?;
1300                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1301                 self.pop_operand(Some(Type::I32))?;
1302                 self.pop_operand(Some(Type::I32))?;
1303                 self.pop_operand(Some(ty))?;
1304                 self.push_operand(Type::I32)?;
1305             }
1306             Operator::I64AtomicRmwXchg { memarg }
1307             | Operator::I64AtomicRmw32XchgU { memarg }
1308             | Operator::I64AtomicRmw16XchgU { memarg }
1309             | Operator::I64AtomicRmw8XchgU { memarg } => {
1310                 self.check_threads_enabled()?;
1311                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1312                 self.pop_operand(Some(Type::I64))?;
1313                 self.pop_operand(Some(ty))?;
1314                 self.push_operand(Type::I64)?;
1315             }
1316             Operator::I64AtomicRmwCmpxchg { memarg }
1317             | Operator::I64AtomicRmw32CmpxchgU { memarg }
1318             | Operator::I64AtomicRmw16CmpxchgU { memarg }
1319             | Operator::I64AtomicRmw8CmpxchgU { memarg } => {
1320                 self.check_threads_enabled()?;
1321                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1322                 self.pop_operand(Some(Type::I64))?;
1323                 self.pop_operand(Some(Type::I64))?;
1324                 self.pop_operand(Some(ty))?;
1325                 self.push_operand(Type::I64)?;
1326             }
1327             Operator::MemoryAtomicNotify { memarg } => {
1328                 self.check_threads_enabled()?;
1329                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1330                 self.pop_operand(Some(Type::I32))?;
1331                 self.pop_operand(Some(ty))?;
1332                 self.push_operand(Type::I32)?;
1333             }
1334             Operator::MemoryAtomicWait32 { memarg } => {
1335                 self.check_threads_enabled()?;
1336                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1337                 self.pop_operand(Some(Type::I64))?;
1338                 self.pop_operand(Some(Type::I32))?;
1339                 self.pop_operand(Some(ty))?;
1340                 self.push_operand(Type::I32)?;
1341             }
1342             Operator::MemoryAtomicWait64 { memarg } => {
1343                 self.check_threads_enabled()?;
1344                 let ty = self.check_shared_memarg_wo_align(memarg, resources)?;
1345                 self.pop_operand(Some(Type::I64))?;
1346                 self.pop_operand(Some(Type::I64))?;
1347                 self.pop_operand(Some(ty))?;
1348                 self.push_operand(Type::I32)?;
1349             }
1350             Operator::AtomicFence { ref flags } => {
1351                 self.check_threads_enabled()?;
1352                 if *flags != 0 {
1353                     return Err(OperatorValidatorError::new(
1354                         "non-zero flags for fence not supported yet",
1355                     ));
1356                 }
1357             }
1358             Operator::RefNull { ty } => {
1359                 self.check_reference_types_enabled()?;
1360                 match ty {
1361                     Type::FuncRef | Type::ExternRef => {}
1362                     _ => {
1363                         return Err(OperatorValidatorError::new(
1364                             "invalid reference type in ref.null",
1365                         ))
1366                     }
1367                 }
1368                 self.push_operand(ty)?;
1369             }
1370             Operator::RefIsNull => {
1371                 self.check_reference_types_enabled()?;
1372                 match self.pop_operand(None)? {
1373                     None | Some(Type::FuncRef) | Some(Type::ExternRef) => {}
1374                     _ => {
1375                         return Err(OperatorValidatorError::new(
1376                             "type mismatch: invalid reference type in ref.is_null",
1377                         ))
1378                     }
1379                 }
1380                 self.push_operand(Type::I32)?;
1381             }
1382             Operator::RefFunc { function_index } => {
1383                 self.check_reference_types_enabled()?;
1384                 if resources.type_of_function(function_index).is_none() {
1385                     return Err(OperatorValidatorError::new(
1386                         "unknown function: function index out of bounds",
1387                     ));
1388                 }
1389                 if !resources.is_function_referenced(function_index) {
1390                     return Err(OperatorValidatorError::new("undeclared function reference"));
1391                 }
1392                 self.push_operand(Type::FuncRef)?;
1393             }
1394             Operator::V128Load { memarg } => {
1395                 self.check_simd_enabled()?;
1396                 let ty = self.check_memarg(memarg, 4, resources)?;
1397                 self.pop_operand(Some(ty))?;
1398                 self.push_operand(Type::V128)?;
1399             }
1400             Operator::V128Store { memarg } => {
1401                 self.check_simd_enabled()?;
1402                 let ty = self.check_memarg(memarg, 4, resources)?;
1403                 self.pop_operand(Some(Type::V128))?;
1404                 self.pop_operand(Some(ty))?;
1405             }
1406             Operator::V128Const { .. } => {
1407                 self.check_simd_enabled()?;
1408                 self.push_operand(Type::V128)?;
1409             }
1410             Operator::I8x16Splat | Operator::I16x8Splat | Operator::I32x4Splat => {
1411                 self.check_simd_enabled()?;
1412                 self.pop_operand(Some(Type::I32))?;
1413                 self.push_operand(Type::V128)?;
1414             }
1415             Operator::I64x2Splat => {
1416                 self.check_simd_enabled()?;
1417                 self.pop_operand(Some(Type::I64))?;
1418                 self.push_operand(Type::V128)?;
1419             }
1420             Operator::F32x4Splat => {
1421                 self.check_non_deterministic_enabled()?;
1422                 self.check_simd_enabled()?;
1423                 self.pop_operand(Some(Type::F32))?;
1424                 self.push_operand(Type::V128)?;
1425             }
1426             Operator::F64x2Splat => {
1427                 self.check_non_deterministic_enabled()?;
1428                 self.check_simd_enabled()?;
1429                 self.pop_operand(Some(Type::F64))?;
1430                 self.push_operand(Type::V128)?;
1431             }
1432             Operator::I8x16ExtractLaneS { lane } | Operator::I8x16ExtractLaneU { lane } => {
1433                 self.check_simd_enabled()?;
1434                 self.check_simd_lane_index(lane, 16)?;
1435                 self.pop_operand(Some(Type::V128))?;
1436                 self.push_operand(Type::I32)?;
1437             }
1438             Operator::I16x8ExtractLaneS { lane } | Operator::I16x8ExtractLaneU { lane } => {
1439                 self.check_simd_enabled()?;
1440                 self.check_simd_lane_index(lane, 8)?;
1441                 self.pop_operand(Some(Type::V128))?;
1442                 self.push_operand(Type::I32)?;
1443             }
1444             Operator::I32x4ExtractLane { lane } => {
1445                 self.check_simd_enabled()?;
1446                 self.check_simd_lane_index(lane, 4)?;
1447                 self.pop_operand(Some(Type::V128))?;
1448                 self.push_operand(Type::I32)?;
1449             }
1450             Operator::I8x16ReplaceLane { lane } => {
1451                 self.check_simd_enabled()?;
1452                 self.check_simd_lane_index(lane, 16)?;
1453                 self.pop_operand(Some(Type::I32))?;
1454                 self.pop_operand(Some(Type::V128))?;
1455                 self.push_operand(Type::V128)?;
1456             }
1457             Operator::I16x8ReplaceLane { lane } => {
1458                 self.check_simd_enabled()?;
1459                 self.check_simd_lane_index(lane, 8)?;
1460                 self.pop_operand(Some(Type::I32))?;
1461                 self.pop_operand(Some(Type::V128))?;
1462                 self.push_operand(Type::V128)?;
1463             }
1464             Operator::I32x4ReplaceLane { lane } => {
1465                 self.check_simd_enabled()?;
1466                 self.check_simd_lane_index(lane, 4)?;
1467                 self.pop_operand(Some(Type::I32))?;
1468                 self.pop_operand(Some(Type::V128))?;
1469                 self.push_operand(Type::V128)?;
1470             }
1471             Operator::I64x2ExtractLane { lane } => {
1472                 self.check_simd_enabled()?;
1473                 self.check_simd_lane_index(lane, 2)?;
1474                 self.pop_operand(Some(Type::V128))?;
1475                 self.push_operand(Type::I64)?;
1476             }
1477             Operator::I64x2ReplaceLane { lane } => {
1478                 self.check_simd_enabled()?;
1479                 self.check_simd_lane_index(lane, 2)?;
1480                 self.pop_operand(Some(Type::I64))?;
1481                 self.pop_operand(Some(Type::V128))?;
1482                 self.push_operand(Type::V128)?;
1483             }
1484             Operator::F32x4ExtractLane { lane } => {
1485                 self.check_non_deterministic_enabled()?;
1486                 self.check_simd_enabled()?;
1487                 self.check_simd_lane_index(lane, 4)?;
1488                 self.pop_operand(Some(Type::V128))?;
1489                 self.push_operand(Type::F32)?;
1490             }
1491             Operator::F32x4ReplaceLane { lane } => {
1492                 self.check_non_deterministic_enabled()?;
1493                 self.check_simd_enabled()?;
1494                 self.check_simd_lane_index(lane, 4)?;
1495                 self.pop_operand(Some(Type::F32))?;
1496                 self.pop_operand(Some(Type::V128))?;
1497                 self.push_operand(Type::V128)?;
1498             }
1499             Operator::F64x2ExtractLane { lane } => {
1500                 self.check_non_deterministic_enabled()?;
1501                 self.check_simd_enabled()?;
1502                 self.check_simd_lane_index(lane, 2)?;
1503                 self.pop_operand(Some(Type::V128))?;
1504                 self.push_operand(Type::F64)?;
1505             }
1506             Operator::F64x2ReplaceLane { lane } => {
1507                 self.check_non_deterministic_enabled()?;
1508                 self.check_simd_enabled()?;
1509                 self.check_simd_lane_index(lane, 2)?;
1510                 self.pop_operand(Some(Type::F64))?;
1511                 self.pop_operand(Some(Type::V128))?;
1512                 self.push_operand(Type::V128)?;
1513             }
1514             Operator::F32x4Eq
1515             | Operator::F32x4Ne
1516             | Operator::F32x4Lt
1517             | Operator::F32x4Gt
1518             | Operator::F32x4Le
1519             | Operator::F32x4Ge
1520             | Operator::F64x2Eq
1521             | Operator::F64x2Ne
1522             | Operator::F64x2Lt
1523             | Operator::F64x2Gt
1524             | Operator::F64x2Le
1525             | Operator::F64x2Ge
1526             | Operator::F32x4Add
1527             | Operator::F32x4Sub
1528             | Operator::F32x4Mul
1529             | Operator::F32x4Div
1530             | Operator::F32x4Min
1531             | Operator::F32x4Max
1532             | Operator::F32x4PMin
1533             | Operator::F32x4PMax
1534             | Operator::F64x2Add
1535             | Operator::F64x2Sub
1536             | Operator::F64x2Mul
1537             | Operator::F64x2Div
1538             | Operator::F64x2Min
1539             | Operator::F64x2Max
1540             | Operator::F64x2PMin
1541             | Operator::F64x2PMax => {
1542                 self.check_non_deterministic_enabled()?;
1543                 self.check_simd_enabled()?;
1544                 self.pop_operand(Some(Type::V128))?;
1545                 self.pop_operand(Some(Type::V128))?;
1546                 self.push_operand(Type::V128)?;
1547             }
1548             Operator::I8x16Eq
1549             | Operator::I8x16Ne
1550             | Operator::I8x16LtS
1551             | Operator::I8x16LtU
1552             | Operator::I8x16GtS
1553             | Operator::I8x16GtU
1554             | Operator::I8x16LeS
1555             | Operator::I8x16LeU
1556             | Operator::I8x16GeS
1557             | Operator::I8x16GeU
1558             | Operator::I16x8Eq
1559             | Operator::I16x8Ne
1560             | Operator::I16x8LtS
1561             | Operator::I16x8LtU
1562             | Operator::I16x8GtS
1563             | Operator::I16x8GtU
1564             | Operator::I16x8LeS
1565             | Operator::I16x8LeU
1566             | Operator::I16x8GeS
1567             | Operator::I16x8GeU
1568             | Operator::I32x4Eq
1569             | Operator::I32x4Ne
1570             | Operator::I32x4LtS
1571             | Operator::I32x4LtU
1572             | Operator::I32x4GtS
1573             | Operator::I32x4GtU
1574             | Operator::I32x4LeS
1575             | Operator::I32x4LeU
1576             | Operator::I32x4GeS
1577             | Operator::I32x4GeU
1578             | Operator::I64x2Eq
1579             | Operator::I64x2Ne
1580             | Operator::I64x2LtS
1581             | Operator::I64x2GtS
1582             | Operator::I64x2LeS
1583             | Operator::I64x2GeS
1584             | Operator::V128And
1585             | Operator::V128AndNot
1586             | Operator::V128Or
1587             | Operator::V128Xor
1588             | Operator::I8x16Add
1589             | Operator::I8x16AddSatS
1590             | Operator::I8x16AddSatU
1591             | Operator::I8x16Sub
1592             | Operator::I8x16SubSatS
1593             | Operator::I8x16SubSatU
1594             | Operator::I8x16MinS
1595             | Operator::I8x16MinU
1596             | Operator::I8x16MaxS
1597             | Operator::I8x16MaxU
1598             | Operator::I16x8Add
1599             | Operator::I16x8AddSatS
1600             | Operator::I16x8AddSatU
1601             | Operator::I16x8Sub
1602             | Operator::I16x8SubSatS
1603             | Operator::I16x8SubSatU
1604             | Operator::I16x8Mul
1605             | Operator::I16x8MinS
1606             | Operator::I16x8MinU
1607             | Operator::I16x8MaxS
1608             | Operator::I16x8MaxU
1609             | Operator::I32x4Add
1610             | Operator::I32x4Sub
1611             | Operator::I32x4Mul
1612             | Operator::I32x4MinS
1613             | Operator::I32x4MinU
1614             | Operator::I32x4MaxS
1615             | Operator::I32x4MaxU
1616             | Operator::I32x4DotI16x8S
1617             | Operator::I64x2Add
1618             | Operator::I64x2Sub
1619             | Operator::I64x2Mul
1620             | Operator::I8x16RoundingAverageU
1621             | Operator::I16x8RoundingAverageU
1622             | Operator::I8x16NarrowI16x8S
1623             | Operator::I8x16NarrowI16x8U
1624             | Operator::I16x8NarrowI32x4S
1625             | Operator::I16x8NarrowI32x4U
1626             | Operator::I16x8ExtMulLowI8x16S
1627             | Operator::I16x8ExtMulHighI8x16S
1628             | Operator::I16x8ExtMulLowI8x16U
1629             | Operator::I16x8ExtMulHighI8x16U
1630             | Operator::I32x4ExtMulLowI16x8S
1631             | Operator::I32x4ExtMulHighI16x8S
1632             | Operator::I32x4ExtMulLowI16x8U
1633             | Operator::I32x4ExtMulHighI16x8U
1634             | Operator::I64x2ExtMulLowI32x4S
1635             | Operator::I64x2ExtMulHighI32x4S
1636             | Operator::I64x2ExtMulLowI32x4U
1637             | Operator::I64x2ExtMulHighI32x4U
1638             | Operator::I16x8Q15MulrSatS => {
1639                 self.check_simd_enabled()?;
1640                 self.pop_operand(Some(Type::V128))?;
1641                 self.pop_operand(Some(Type::V128))?;
1642                 self.push_operand(Type::V128)?;
1643             }
1644             Operator::F32x4Ceil
1645             | Operator::F32x4Floor
1646             | Operator::F32x4Trunc
1647             | Operator::F32x4Nearest
1648             | Operator::F64x2Ceil
1649             | Operator::F64x2Floor
1650             | Operator::F64x2Trunc
1651             | Operator::F64x2Nearest
1652             | Operator::F32x4Abs
1653             | Operator::F32x4Neg
1654             | Operator::F32x4Sqrt
1655             | Operator::F64x2Abs
1656             | Operator::F64x2Neg
1657             | Operator::F64x2Sqrt
1658             | Operator::F32x4DemoteF64x2Zero
1659             | Operator::F64x2PromoteLowF32x4
1660             | Operator::F64x2ConvertLowI32x4S
1661             | Operator::F64x2ConvertLowI32x4U
1662             | Operator::I32x4TruncSatF64x2SZero
1663             | Operator::I32x4TruncSatF64x2UZero
1664             | Operator::F32x4ConvertI32x4S
1665             | Operator::F32x4ConvertI32x4U => {
1666                 self.check_non_deterministic_enabled()?;
1667                 self.check_simd_enabled()?;
1668                 self.pop_operand(Some(Type::V128))?;
1669                 self.push_operand(Type::V128)?;
1670             }
1671             Operator::V128Not
1672             | Operator::I8x16Abs
1673             | Operator::I8x16Neg
1674             | Operator::I8x16Popcnt
1675             | Operator::I16x8Abs
1676             | Operator::I16x8Neg
1677             | Operator::I32x4Abs
1678             | Operator::I32x4Neg
1679             | Operator::I64x2Abs
1680             | Operator::I64x2Neg
1681             | Operator::I32x4TruncSatF32x4S
1682             | Operator::I32x4TruncSatF32x4U
1683             | Operator::I16x8ExtendLowI8x16S
1684             | Operator::I16x8ExtendHighI8x16S
1685             | Operator::I16x8ExtendLowI8x16U
1686             | Operator::I16x8ExtendHighI8x16U
1687             | Operator::I32x4ExtendLowI16x8S
1688             | Operator::I32x4ExtendHighI16x8S
1689             | Operator::I32x4ExtendLowI16x8U
1690             | Operator::I32x4ExtendHighI16x8U
1691             | Operator::I64x2ExtendLowI32x4S
1692             | Operator::I64x2ExtendHighI32x4S
1693             | Operator::I64x2ExtendLowI32x4U
1694             | Operator::I64x2ExtendHighI32x4U
1695             | Operator::I16x8ExtAddPairwiseI8x16S
1696             | Operator::I16x8ExtAddPairwiseI8x16U
1697             | Operator::I32x4ExtAddPairwiseI16x8S
1698             | Operator::I32x4ExtAddPairwiseI16x8U => {
1699                 self.check_simd_enabled()?;
1700                 self.pop_operand(Some(Type::V128))?;
1701                 self.push_operand(Type::V128)?;
1702             }
1703             Operator::V128Bitselect => {
1704                 self.check_simd_enabled()?;
1705                 self.pop_operand(Some(Type::V128))?;
1706                 self.pop_operand(Some(Type::V128))?;
1707                 self.pop_operand(Some(Type::V128))?;
1708                 self.push_operand(Type::V128)?;
1709             }
1710             Operator::V128AnyTrue
1711             | Operator::I8x16AllTrue
1712             | Operator::I8x16Bitmask
1713             | Operator::I16x8AllTrue
1714             | Operator::I16x8Bitmask
1715             | Operator::I32x4AllTrue
1716             | Operator::I32x4Bitmask
1717             | Operator::I64x2AllTrue
1718             | Operator::I64x2Bitmask => {
1719                 self.check_simd_enabled()?;
1720                 self.pop_operand(Some(Type::V128))?;
1721                 self.push_operand(Type::I32)?;
1722             }
1723             Operator::I8x16Shl
1724             | Operator::I8x16ShrS
1725             | Operator::I8x16ShrU
1726             | Operator::I16x8Shl
1727             | Operator::I16x8ShrS
1728             | Operator::I16x8ShrU
1729             | Operator::I32x4Shl
1730             | Operator::I32x4ShrS
1731             | Operator::I32x4ShrU
1732             | Operator::I64x2Shl
1733             | Operator::I64x2ShrS
1734             | Operator::I64x2ShrU => {
1735                 self.check_simd_enabled()?;
1736                 self.pop_operand(Some(Type::I32))?;
1737                 self.pop_operand(Some(Type::V128))?;
1738                 self.push_operand(Type::V128)?;
1739             }
1740             Operator::I8x16Swizzle => {
1741                 self.check_simd_enabled()?;
1742                 self.pop_operand(Some(Type::V128))?;
1743                 self.pop_operand(Some(Type::V128))?;
1744                 self.push_operand(Type::V128)?;
1745             }
1746             Operator::I8x16Shuffle { ref lanes } => {
1747                 self.check_simd_enabled()?;
1748                 self.pop_operand(Some(Type::V128))?;
1749                 self.pop_operand(Some(Type::V128))?;
1750                 for i in lanes {
1751                     self.check_simd_lane_index(*i, 32)?;
1752                 }
1753                 self.push_operand(Type::V128)?;
1754             }
1755             Operator::V128Load8Splat { memarg } => {
1756                 self.check_simd_enabled()?;
1757                 let ty = self.check_memarg(memarg, 0, resources)?;
1758                 self.pop_operand(Some(ty))?;
1759                 self.push_operand(Type::V128)?;
1760             }
1761             Operator::V128Load16Splat { memarg } => {
1762                 self.check_simd_enabled()?;
1763                 let ty = self.check_memarg(memarg, 1, resources)?;
1764                 self.pop_operand(Some(ty))?;
1765                 self.push_operand(Type::V128)?;
1766             }
1767             Operator::V128Load32Splat { memarg } | Operator::V128Load32Zero { memarg } => {
1768                 self.check_simd_enabled()?;
1769                 let ty = self.check_memarg(memarg, 2, resources)?;
1770                 self.pop_operand(Some(ty))?;
1771                 self.push_operand(Type::V128)?;
1772             }
1773             Operator::V128Load64Splat { memarg }
1774             | Operator::V128Load64Zero { memarg }
1775             | Operator::V128Load8x8S { memarg }
1776             | Operator::V128Load8x8U { memarg }
1777             | Operator::V128Load16x4S { memarg }
1778             | Operator::V128Load16x4U { memarg }
1779             | Operator::V128Load32x2S { memarg }
1780             | Operator::V128Load32x2U { memarg } => {
1781                 self.check_simd_enabled()?;
1782                 let idx = self.check_memarg(memarg, 3, resources)?;
1783                 self.pop_operand(Some(idx))?;
1784                 self.push_operand(Type::V128)?;
1785             }
1786             Operator::V128Load8Lane { memarg, lane } => {
1787                 self.check_simd_enabled()?;
1788                 let idx = self.check_memarg(memarg, 0, resources)?;
1789                 self.check_simd_lane_index(lane, 16)?;
1790                 self.pop_operand(Some(Type::V128))?;
1791                 self.pop_operand(Some(idx))?;
1792                 self.push_operand(Type::V128)?;
1793             }
1794             Operator::V128Load16Lane { memarg, lane } => {
1795                 self.check_simd_enabled()?;
1796                 let idx = self.check_memarg(memarg, 1, resources)?;
1797                 self.check_simd_lane_index(lane, 8)?;
1798                 self.pop_operand(Some(Type::V128))?;
1799                 self.pop_operand(Some(idx))?;
1800                 self.push_operand(Type::V128)?;
1801             }
1802             Operator::V128Load32Lane { memarg, lane } => {
1803                 self.check_simd_enabled()?;
1804                 let idx = self.check_memarg(memarg, 2, resources)?;
1805                 self.check_simd_lane_index(lane, 4)?;
1806                 self.pop_operand(Some(Type::V128))?;
1807                 self.pop_operand(Some(idx))?;
1808                 self.push_operand(Type::V128)?;
1809             }
1810             Operator::V128Load64Lane { memarg, lane } => {
1811                 self.check_simd_enabled()?;
1812                 let idx = self.check_memarg(memarg, 3, resources)?;
1813                 self.check_simd_lane_index(lane, 2)?;
1814                 self.pop_operand(Some(Type::V128))?;
1815                 self.pop_operand(Some(idx))?;
1816                 self.push_operand(Type::V128)?;
1817             }
1818             Operator::V128Store8Lane { memarg, lane } => {
1819                 self.check_simd_enabled()?;
1820                 let idx = self.check_memarg(memarg, 0, resources)?;
1821                 self.check_simd_lane_index(lane, 16)?;
1822                 self.pop_operand(Some(Type::V128))?;
1823                 self.pop_operand(Some(idx))?;
1824             }
1825             Operator::V128Store16Lane { memarg, lane } => {
1826                 self.check_simd_enabled()?;
1827                 let idx = self.check_memarg(memarg, 1, resources)?;
1828                 self.check_simd_lane_index(lane, 8)?;
1829                 self.pop_operand(Some(Type::V128))?;
1830                 self.pop_operand(Some(idx))?;
1831             }
1832             Operator::V128Store32Lane { memarg, lane } => {
1833                 self.check_simd_enabled()?;
1834                 let idx = self.check_memarg(memarg, 2, resources)?;
1835                 self.check_simd_lane_index(lane, 4)?;
1836                 self.pop_operand(Some(Type::V128))?;
1837                 self.pop_operand(Some(idx))?;
1838             }
1839             Operator::V128Store64Lane { memarg, lane } => {
1840                 self.check_simd_enabled()?;
1841                 let idx = self.check_memarg(memarg, 3, resources)?;
1842                 self.check_simd_lane_index(lane, 2)?;
1843                 self.pop_operand(Some(Type::V128))?;
1844                 self.pop_operand(Some(idx))?;
1845             }
1846             Operator::MemoryInit { mem, segment } => {
1847                 self.check_bulk_memory_enabled()?;
1848                 let ty = self.check_memory_index(mem, resources)?;
1849                 if segment >= resources.data_count() {
1850                     bail_op_err!("unknown data segment {}", segment);
1851                 }
1852                 self.pop_operand(Some(Type::I32))?;
1853                 self.pop_operand(Some(Type::I32))?;
1854                 self.pop_operand(Some(ty))?;
1855             }
1856             Operator::DataDrop { segment } => {
1857                 self.check_bulk_memory_enabled()?;
1858                 if segment >= resources.data_count() {
1859                     bail_op_err!("unknown data segment {}", segment);
1860                 }
1861             }
1862             Operator::MemoryCopy { src, dst } => {
1863                 self.check_bulk_memory_enabled()?;
1864                 let dst_ty = self.check_memory_index(dst, resources)?;
1865                 let src_ty = self.check_memory_index(src, resources)?;
1866                 self.pop_operand(Some(match src_ty {
1867                     Type::I32 => Type::I32,
1868                     _ => dst_ty,
1869                 }))?;
1870                 self.pop_operand(Some(src_ty))?;
1871                 self.pop_operand(Some(dst_ty))?;
1872             }
1873             Operator::MemoryFill { mem } => {
1874                 self.check_bulk_memory_enabled()?;
1875                 let ty = self.check_memory_index(mem, resources)?;
1876                 self.pop_operand(Some(ty))?;
1877                 self.pop_operand(Some(Type::I32))?;
1878                 self.pop_operand(Some(ty))?;
1879             }
1880             Operator::TableInit { segment, table } => {
1881                 self.check_bulk_memory_enabled()?;
1882                 if table > 0 {
1883                     self.check_reference_types_enabled()?;
1884                 }
1885                 let table = match resources.table_at(table) {
1886                     Some(table) => table,
1887                     None => bail_op_err!("unknown table {}: table index out of bounds", table),
1888                 };
1889                 let segment_ty = match resources.element_type_at(segment) {
1890                     Some(ty) => ty,
1891                     None => bail_op_err!(
1892                         "unknown elem segment {}: segment index out of bounds",
1893                         segment
1894                     ),
1895                 };
1896                 if segment_ty != table.element_type {
1897                     return Err(OperatorValidatorError::new("type mismatch"));
1898                 }
1899                 self.pop_operand(Some(Type::I32))?;
1900                 self.pop_operand(Some(Type::I32))?;
1901                 self.pop_operand(Some(Type::I32))?;
1902             }
1903             Operator::ElemDrop { segment } => {
1904                 self.check_bulk_memory_enabled()?;
1905                 if segment >= resources.element_count() {
1906                     bail_op_err!(
1907                         "unknown elem segment {}: segment index out of bounds",
1908                         segment
1909                     );
1910                 }
1911             }
1912             Operator::TableCopy {
1913                 src_table,
1914                 dst_table,
1915             } => {
1916                 self.check_bulk_memory_enabled()?;
1917                 if src_table > 0 || dst_table > 0 {
1918                     self.check_reference_types_enabled()?;
1919                 }
1920                 let (src, dst) =
1921                     match (resources.table_at(src_table), resources.table_at(dst_table)) {
1922                         (Some(a), Some(b)) => (a, b),
1923                         _ => return Err(OperatorValidatorError::new("table index out of bounds")),
1924                     };
1925                 if src.element_type != dst.element_type {
1926                     return Err(OperatorValidatorError::new("type mismatch"));
1927                 }
1928                 self.pop_operand(Some(Type::I32))?;
1929                 self.pop_operand(Some(Type::I32))?;
1930                 self.pop_operand(Some(Type::I32))?;
1931             }
1932             Operator::TableGet { table } => {
1933                 self.check_reference_types_enabled()?;
1934                 let ty = match resources.table_at(table) {
1935                     Some(ty) => ty.element_type,
1936                     None => return Err(OperatorValidatorError::new("table index out of bounds")),
1937                 };
1938                 self.pop_operand(Some(Type::I32))?;
1939                 self.push_operand(ty)?;
1940             }
1941             Operator::TableSet { table } => {
1942                 self.check_reference_types_enabled()?;
1943                 let ty = match resources.table_at(table) {
1944                     Some(ty) => ty.element_type,
1945                     None => return Err(OperatorValidatorError::new("table index out of bounds")),
1946                 };
1947                 self.pop_operand(Some(ty))?;
1948                 self.pop_operand(Some(Type::I32))?;
1949             }
1950             Operator::TableGrow { table } => {
1951                 self.check_reference_types_enabled()?;
1952                 let ty = match resources.table_at(table) {
1953                     Some(ty) => ty.element_type,
1954                     None => return Err(OperatorValidatorError::new("table index out of bounds")),
1955                 };
1956                 self.pop_operand(Some(Type::I32))?;
1957                 self.pop_operand(Some(ty))?;
1958                 self.push_operand(Type::I32)?;
1959             }
1960             Operator::TableSize { table } => {
1961                 self.check_reference_types_enabled()?;
1962                 if resources.table_at(table).is_none() {
1963                     return Err(OperatorValidatorError::new("table index out of bounds"));
1964                 }
1965                 self.push_operand(Type::I32)?;
1966             }
1967             Operator::TableFill { table } => {
1968                 self.check_bulk_memory_enabled()?;
1969                 let ty = match resources.table_at(table) {
1970                     Some(ty) => ty.element_type,
1971                     None => return Err(OperatorValidatorError::new("table index out of bounds")),
1972                 };
1973                 self.pop_operand(Some(Type::I32))?;
1974                 self.pop_operand(Some(ty))?;
1975                 self.pop_operand(Some(Type::I32))?;
1976             }
1977         }
1978         Ok(())
1979     }
1980 
finish(&mut self) -> OperatorValidatorResult<()>1981     pub fn finish(&mut self) -> OperatorValidatorResult<()> {
1982         if self.control.len() != 0 {
1983             bail_op_err!("control frames remain at end of function");
1984         }
1985         Ok(())
1986     }
1987 }
1988 
func_type_at<T: WasmModuleResources>( resources: &T, at: u32, ) -> OperatorValidatorResult<&T::FuncType>1989 fn func_type_at<T: WasmModuleResources>(
1990     resources: &T,
1991     at: u32,
1992 ) -> OperatorValidatorResult<&T::FuncType> {
1993     resources
1994         .func_type_at(at)
1995         .ok_or_else(|| OperatorValidatorError::new("unknown type: type index out of bounds"))
1996 }
1997 
event_at<T: WasmModuleResources>( resources: &T, at: u32, ) -> OperatorValidatorResult<&T::FuncType>1998 fn event_at<T: WasmModuleResources>(
1999     resources: &T,
2000     at: u32,
2001 ) -> OperatorValidatorResult<&T::FuncType> {
2002     resources
2003         .event_at(at)
2004         .ok_or_else(|| OperatorValidatorError::new("unknown event: event index out of bounds"))
2005 }
2006 
2007 enum Either<A, B> {
2008     A(A),
2009     B(B),
2010 }
2011 
2012 impl<A, B> Iterator for Either<A, B>
2013 where
2014     A: Iterator,
2015     B: Iterator<Item = A::Item>,
2016 {
2017     type Item = A::Item;
next(&mut self) -> Option<A::Item>2018     fn next(&mut self) -> Option<A::Item> {
2019         match self {
2020             Either::A(a) => a.next(),
2021             Either::B(b) => b.next(),
2022         }
2023     }
2024 }
2025 impl<A, B> DoubleEndedIterator for Either<A, B>
2026 where
2027     A: DoubleEndedIterator,
2028     B: DoubleEndedIterator<Item = A::Item>,
2029 {
next_back(&mut self) -> Option<A::Item>2030     fn next_back(&mut self) -> Option<A::Item> {
2031         match self {
2032             Either::A(a) => a.next_back(),
2033             Either::B(b) => b.next_back(),
2034         }
2035     }
2036 }
2037 
params<'a>( ty: TypeOrFuncType, resources: &'a impl WasmModuleResources, ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a>2038 fn params<'a>(
2039     ty: TypeOrFuncType,
2040     resources: &'a impl WasmModuleResources,
2041 ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a> {
2042     Ok(match ty {
2043         TypeOrFuncType::FuncType(t) => Either::A(func_type_at(resources, t)?.inputs()),
2044         TypeOrFuncType::Type(_) => Either::B(None.into_iter()),
2045     })
2046 }
2047 
results<'a>( ty: TypeOrFuncType, resources: &'a impl WasmModuleResources, ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a>2048 fn results<'a>(
2049     ty: TypeOrFuncType,
2050     resources: &'a impl WasmModuleResources,
2051 ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a> {
2052     Ok(match ty {
2053         TypeOrFuncType::FuncType(t) => Either::A(func_type_at(resources, t)?.outputs()),
2054         TypeOrFuncType::Type(Type::EmptyBlockType) => Either::B(None.into_iter()),
2055         TypeOrFuncType::Type(t) => Either::B(Some(t).into_iter()),
2056     })
2057 }
2058 
label_types<'a>( ty: TypeOrFuncType, resources: &'a impl WasmModuleResources, kind: FrameKind, ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a>2059 fn label_types<'a>(
2060     ty: TypeOrFuncType,
2061     resources: &'a impl WasmModuleResources,
2062     kind: FrameKind,
2063 ) -> OperatorValidatorResult<impl DoubleEndedIterator<Item = Type> + 'a> {
2064     Ok(match kind {
2065         FrameKind::Loop => Either::A(params(ty, resources)?),
2066         _ => Either::B(results(ty, resources)?),
2067     })
2068 }
2069 
ty_to_str(ty: Type) -> &'static str2070 fn ty_to_str(ty: Type) -> &'static str {
2071     match ty {
2072         Type::I32 => "i32",
2073         Type::I64 => "i64",
2074         Type::F32 => "f32",
2075         Type::F64 => "f64",
2076         Type::V128 => "v128",
2077         Type::FuncRef => "funcref",
2078         Type::ExternRef => "externref",
2079         Type::ExnRef => "exnref",
2080         Type::Func => "func",
2081         Type::EmptyBlockType => "nil",
2082     }
2083 }
2084