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 use core::cmp::min;
17 use core::result;
18 use std::str;
19 use std::vec::Vec;
20
21 use crate::primitives::{
22 FuncType, GlobalType, MemoryImmediate, MemoryType, Operator, SIMDLaneIndex, TableType, Type,
23 TypeOrFuncType,
24 };
25
26 /// Test if `subtype` is a subtype of `supertype`.
is_subtype_supertype(subtype: Type, supertype: Type) -> bool27 pub(crate) fn is_subtype_supertype(subtype: Type, supertype: Type) -> bool {
28 match supertype {
29 Type::AnyRef => {
30 subtype == Type::AnyRef || subtype == Type::AnyFunc || subtype == Type::Null
31 }
32 Type::AnyFunc => subtype == Type::AnyFunc || subtype == Type::Null,
33 _ => subtype == supertype,
34 }
35 }
36
37 #[derive(Debug)]
38 struct BlockState {
39 start_types: Vec<Type>,
40 return_types: Vec<Type>,
41 stack_starts_at: usize,
42 jump_to_top: bool,
43 is_else_allowed: bool,
44 is_dead_code: bool,
45 polymorphic_values: Option<usize>,
46 }
47
48 impl BlockState {
is_stack_polymorphic(&self) -> bool49 fn is_stack_polymorphic(&self) -> bool {
50 self.polymorphic_values.is_some()
51 }
52 }
53
54 #[derive(Debug)]
55 struct FuncState {
56 local_types: Vec<Type>,
57 blocks: Vec<BlockState>,
58 stack_types: Vec<Type>,
59 end_function: bool,
60 }
61
62 impl FuncState {
block_at(&self, depth: usize) -> &BlockState63 fn block_at(&self, depth: usize) -> &BlockState {
64 assert!(depth < self.blocks.len());
65 &self.blocks[self.blocks.len() - 1 - depth]
66 }
last_block(&self) -> &BlockState67 fn last_block(&self) -> &BlockState {
68 self.blocks.last().unwrap()
69 }
assert_stack_type_at(&self, index: usize, expected: Type) -> bool70 fn assert_stack_type_at(&self, index: usize, expected: Type) -> bool {
71 let stack_starts_at = self.last_block().stack_starts_at;
72 if self.last_block().is_stack_polymorphic()
73 && stack_starts_at + index >= self.stack_types.len()
74 {
75 return true;
76 }
77 assert!(stack_starts_at + index < self.stack_types.len());
78 is_subtype_supertype(
79 self.stack_types[self.stack_types.len() - 1 - index],
80 expected,
81 )
82 }
assert_block_stack_len(&self, depth: usize, minimal_len: usize) -> bool83 fn assert_block_stack_len(&self, depth: usize, minimal_len: usize) -> bool {
84 assert!(depth < self.blocks.len());
85 let blocks_end = self.blocks.len();
86 let block_offset = blocks_end - 1 - depth;
87 for i in block_offset..blocks_end {
88 if self.blocks[i].is_stack_polymorphic() {
89 return true;
90 }
91 }
92 let block_starts_at = self.blocks[block_offset].stack_starts_at;
93 self.stack_types.len() >= block_starts_at + minimal_len
94 }
assert_last_block_stack_len_exact(&self, len: usize) -> bool95 fn assert_last_block_stack_len_exact(&self, len: usize) -> bool {
96 let block_starts_at = self.last_block().stack_starts_at;
97 if self.last_block().is_stack_polymorphic() {
98 let polymorphic_values = self.last_block().polymorphic_values.unwrap();
99 self.stack_types.len() + polymorphic_values <= block_starts_at + len
100 } else {
101 self.stack_types.len() == block_starts_at + len
102 }
103 }
remove_frame_stack_types(&mut self, remove_count: usize) -> OperatorValidatorResult<()>104 fn remove_frame_stack_types(&mut self, remove_count: usize) -> OperatorValidatorResult<()> {
105 if remove_count == 0 {
106 return Ok(());
107 }
108 let last_block = self.blocks.last_mut().unwrap();
109 if last_block.is_stack_polymorphic() {
110 let len = self.stack_types.len();
111 let remove_non_polymorphic = len
112 .checked_sub(last_block.stack_starts_at)
113 .ok_or("invalid block signature")?
114 .min(remove_count);
115 self.stack_types.truncate(len - remove_non_polymorphic);
116 let polymorphic_values = last_block.polymorphic_values.unwrap();
117 let remove_polymorphic = min(remove_count - remove_non_polymorphic, polymorphic_values);
118 last_block.polymorphic_values = Some(polymorphic_values - remove_polymorphic);
119 } else {
120 assert!(self.stack_types.len() >= last_block.stack_starts_at + remove_count);
121 let keep = self.stack_types.len() - remove_count;
122 self.stack_types.truncate(keep);
123 }
124 Ok(())
125 }
push_block( &mut self, ty: TypeOrFuncType, block_type: BlockType, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>126 fn push_block(
127 &mut self,
128 ty: TypeOrFuncType,
129 block_type: BlockType,
130 resources: &dyn WasmModuleResources,
131 ) -> OperatorValidatorResult<()> {
132 let (start_types, return_types) = match ty {
133 TypeOrFuncType::Type(Type::EmptyBlockType) => (vec![], vec![]),
134 TypeOrFuncType::Type(ty) => (vec![], vec![ty]),
135 TypeOrFuncType::FuncType(idx) => {
136 let ty = &resources.types()[idx as usize];
137 (ty.params.clone().into_vec(), ty.returns.clone().into_vec())
138 }
139 };
140 if block_type == BlockType::If {
141 let last_block = self.blocks.last().unwrap();
142 if !last_block.is_stack_polymorphic()
143 || self.stack_types.len() > last_block.stack_starts_at
144 {
145 self.stack_types.pop();
146 }
147 assert!(self.stack_types.len() >= last_block.stack_starts_at);
148 }
149 for (i, ty) in start_types.iter().rev().enumerate() {
150 if !self.assert_stack_type_at(i, *ty) {
151 return Err("stack operand type mismatch");
152 }
153 }
154 let stack_starts_at = self.stack_types.len() - start_types.len();
155 self.blocks.push(BlockState {
156 start_types,
157 return_types,
158 stack_starts_at,
159 jump_to_top: block_type == BlockType::Loop,
160 is_else_allowed: block_type == BlockType::If,
161 is_dead_code: false,
162 polymorphic_values: None,
163 });
164 Ok(())
165 }
pop_block(&mut self)166 fn pop_block(&mut self) {
167 assert!(self.blocks.len() > 1);
168 let last_block = self.blocks.pop().unwrap();
169 if last_block.is_stack_polymorphic() {
170 assert!(
171 self.stack_types.len()
172 <= last_block.return_types.len() + last_block.stack_starts_at
173 );
174 } else {
175 assert!(
176 self.stack_types.len()
177 == last_block.return_types.len() + last_block.stack_starts_at
178 );
179 }
180 let keep = last_block.stack_starts_at;
181 self.stack_types.truncate(keep);
182 self.stack_types.extend_from_slice(&last_block.return_types);
183 }
reset_block(&mut self)184 fn reset_block(&mut self) {
185 assert!(self.last_block().is_else_allowed);
186 let last_block = self.blocks.last_mut().unwrap();
187 let keep = last_block.stack_starts_at;
188 self.stack_types.truncate(keep);
189 self.stack_types
190 .extend(last_block.start_types.iter().cloned());
191 last_block.is_else_allowed = false;
192 last_block.polymorphic_values = None;
193 }
change_frame(&mut self, remove_count: usize) -> OperatorValidatorResult<()>194 fn change_frame(&mut self, remove_count: usize) -> OperatorValidatorResult<()> {
195 self.remove_frame_stack_types(remove_count)
196 }
change_frame_with_type( &mut self, remove_count: usize, ty: Type, ) -> OperatorValidatorResult<()>197 fn change_frame_with_type(
198 &mut self,
199 remove_count: usize,
200 ty: Type,
201 ) -> OperatorValidatorResult<()> {
202 self.remove_frame_stack_types(remove_count)?;
203 self.stack_types.push(ty);
204 Ok(())
205 }
change_frame_with_types( &mut self, remove_count: usize, new_items: &[Type], ) -> OperatorValidatorResult<()>206 fn change_frame_with_types(
207 &mut self,
208 remove_count: usize,
209 new_items: &[Type],
210 ) -> OperatorValidatorResult<()> {
211 self.remove_frame_stack_types(remove_count)?;
212 if new_items.is_empty() {
213 return Ok(());
214 }
215 self.stack_types.extend_from_slice(new_items);
216 Ok(())
217 }
change_frame_to_exact_types_from(&mut self, depth: usize) -> OperatorValidatorResult<()>218 fn change_frame_to_exact_types_from(&mut self, depth: usize) -> OperatorValidatorResult<()> {
219 let types = self.block_at(depth).return_types.clone();
220 let last_block = self.blocks.last_mut().unwrap();
221 let keep = last_block.stack_starts_at;
222 self.stack_types.truncate(keep);
223 self.stack_types.extend_from_slice(&types);
224 last_block.polymorphic_values = None;
225 Ok(())
226 }
change_frame_after_select(&mut self, ty: Option<Type>) -> OperatorValidatorResult<()>227 fn change_frame_after_select(&mut self, ty: Option<Type>) -> OperatorValidatorResult<()> {
228 self.remove_frame_stack_types(3)?;
229 if ty.is_none() {
230 let last_block = self.blocks.last_mut().unwrap();
231 assert!(last_block.is_stack_polymorphic());
232 last_block.polymorphic_values = Some(last_block.polymorphic_values.unwrap() + 1);
233 return Ok(());
234 }
235 self.stack_types.push(ty.unwrap());
236 Ok(())
237 }
start_dead_code(&mut self)238 fn start_dead_code(&mut self) {
239 let last_block = self.blocks.last_mut().unwrap();
240 let keep = last_block.stack_starts_at;
241 self.stack_types.truncate(keep);
242 last_block.is_dead_code = true;
243 last_block.polymorphic_values = Some(0);
244 }
end_function(&mut self)245 fn end_function(&mut self) {
246 self.end_function = true;
247 }
248 }
249
250 #[derive(Copy, Clone, PartialEq, Eq)]
251 enum BlockType {
252 Block,
253 Loop,
254 If,
255 }
256
257 pub trait WasmModuleResources {
types(&self) -> &[FuncType]258 fn types(&self) -> &[FuncType];
tables(&self) -> &[TableType]259 fn tables(&self) -> &[TableType];
memories(&self) -> &[MemoryType]260 fn memories(&self) -> &[MemoryType];
globals(&self) -> &[GlobalType]261 fn globals(&self) -> &[GlobalType];
func_type_indices(&self) -> &[u32]262 fn func_type_indices(&self) -> &[u32];
element_count(&self) -> u32263 fn element_count(&self) -> u32;
data_count(&self) -> u32264 fn data_count(&self) -> u32;
265 }
266
267 pub enum FunctionEnd {
268 No,
269 Yes,
270 }
271
272 type OperatorValidatorResult<T> = result::Result<T, &'static str>;
273
274 #[derive(Copy, Clone, Debug)]
275 pub struct OperatorValidatorConfig {
276 pub enable_threads: bool,
277 pub enable_reference_types: bool,
278 pub enable_simd: bool,
279 pub enable_bulk_memory: bool,
280 pub enable_multi_value: bool,
281
282 #[cfg(feature = "deterministic")]
283 pub deterministic_only: bool,
284 }
285
286 pub(crate) const DEFAULT_OPERATOR_VALIDATOR_CONFIG: OperatorValidatorConfig =
287 OperatorValidatorConfig {
288 enable_threads: false,
289 enable_reference_types: false,
290 enable_simd: false,
291 enable_bulk_memory: false,
292 enable_multi_value: false,
293
294 #[cfg(feature = "deterministic")]
295 deterministic_only: true,
296 };
297
298 #[derive(Debug)]
299 pub(crate) struct OperatorValidator {
300 func_state: FuncState,
301 config: OperatorValidatorConfig,
302 }
303
304 impl OperatorValidator {
new( func_type: &FuncType, locals: &[(u32, Type)], config: OperatorValidatorConfig, ) -> OperatorValidator305 pub fn new(
306 func_type: &FuncType,
307 locals: &[(u32, Type)],
308 config: OperatorValidatorConfig,
309 ) -> OperatorValidator {
310 let mut local_types = Vec::new();
311 local_types.extend_from_slice(&*func_type.params);
312 for local in locals {
313 for _ in 0..local.0 {
314 local_types.push(local.1);
315 }
316 }
317
318 let mut blocks = Vec::new();
319 let mut last_returns = Vec::new();
320 last_returns.extend_from_slice(&*func_type.returns);
321 blocks.push(BlockState {
322 start_types: vec![],
323 return_types: last_returns,
324 stack_starts_at: 0,
325 jump_to_top: false,
326 is_else_allowed: false,
327 is_dead_code: false,
328 polymorphic_values: None,
329 });
330
331 OperatorValidator {
332 func_state: FuncState {
333 local_types,
334 blocks,
335 stack_types: Vec::new(),
336 end_function: false,
337 },
338 config,
339 }
340 }
341
is_dead_code(&self) -> bool342 pub fn is_dead_code(&self) -> bool {
343 self.func_state.last_block().is_dead_code
344 }
345
check_frame_size(&self, require_count: usize) -> OperatorValidatorResult<()>346 fn check_frame_size(&self, require_count: usize) -> OperatorValidatorResult<()> {
347 if !self.func_state.assert_block_stack_len(0, require_count) {
348 Err("not enough operands")
349 } else {
350 Ok(())
351 }
352 }
353
check_operands_1(&self, operand: Type) -> OperatorValidatorResult<()>354 fn check_operands_1(&self, operand: Type) -> OperatorValidatorResult<()> {
355 self.check_frame_size(1)?;
356 if !self.func_state.assert_stack_type_at(0, operand) {
357 return Err("stack operand type mismatch");
358 }
359 Ok(())
360 }
361
check_operands_2(&self, operand1: Type, operand2: Type) -> OperatorValidatorResult<()>362 fn check_operands_2(&self, operand1: Type, operand2: Type) -> OperatorValidatorResult<()> {
363 self.check_frame_size(2)?;
364 if !self.func_state.assert_stack_type_at(1, operand1) {
365 return Err("stack operand type mismatch");
366 }
367 if !self.func_state.assert_stack_type_at(0, operand2) {
368 return Err("stack operand type mismatch");
369 }
370 Ok(())
371 }
372
check_operands(&self, expected_types: &[Type]) -> OperatorValidatorResult<()>373 fn check_operands(&self, expected_types: &[Type]) -> OperatorValidatorResult<()> {
374 let len = expected_types.len();
375 self.check_frame_size(len)?;
376 for i in 0..len {
377 if !self
378 .func_state
379 .assert_stack_type_at(len - 1 - i, expected_types[i])
380 {
381 return Err("stack operand type mismatch");
382 }
383 }
384 Ok(())
385 }
386
check_block_return_types( &self, block: &BlockState, reserve_items: usize, ) -> OperatorValidatorResult<()>387 fn check_block_return_types(
388 &self,
389 block: &BlockState,
390 reserve_items: usize,
391 ) -> OperatorValidatorResult<()> {
392 if !self.config.enable_multi_value && block.return_types.len() > 1 {
393 return Err("blocks, loops, and ifs may only return at most one \
394 value when multi-value is not enabled");
395 }
396 let len = block.return_types.len();
397 for i in 0..len {
398 if !self
399 .func_state
400 .assert_stack_type_at(len - 1 - i + reserve_items, block.return_types[i])
401 {
402 return Err("stack item type does not match block item type");
403 }
404 }
405 Ok(())
406 }
407
check_block_return(&self) -> OperatorValidatorResult<()>408 fn check_block_return(&self) -> OperatorValidatorResult<()> {
409 let len = self.func_state.last_block().return_types.len();
410 if !self.func_state.assert_last_block_stack_len_exact(len) {
411 return Err("stack size does not match block type");
412 }
413 self.check_block_return_types(self.func_state.last_block(), 0)
414 }
415
check_jump_from_block( &self, relative_depth: u32, reserve_items: usize, ) -> OperatorValidatorResult<()>416 fn check_jump_from_block(
417 &self,
418 relative_depth: u32,
419 reserve_items: usize,
420 ) -> OperatorValidatorResult<()> {
421 if relative_depth as usize >= self.func_state.blocks.len() {
422 return Err("invalid block depth");
423 }
424 let block = self.func_state.block_at(relative_depth as usize);
425 if block.jump_to_top {
426 if !self.func_state.assert_block_stack_len(0, reserve_items) {
427 return Err("stack size does not match target loop type");
428 }
429 return Ok(());
430 }
431
432 let len = block.return_types.len();
433 if !self
434 .func_state
435 .assert_block_stack_len(0, len + reserve_items)
436 {
437 return Err("stack size does not match target block type");
438 }
439 self.check_block_return_types(block, reserve_items)
440 }
441
match_block_return(&self, depth1: u32, depth2: u32) -> OperatorValidatorResult<()>442 fn match_block_return(&self, depth1: u32, depth2: u32) -> OperatorValidatorResult<()> {
443 if depth1 as usize >= self.func_state.blocks.len() {
444 return Err("invalid block depth");
445 }
446 if depth2 as usize >= self.func_state.blocks.len() {
447 return Err("invalid block depth");
448 }
449 let block1 = self.func_state.block_at(depth1 as usize);
450 let block2 = self.func_state.block_at(depth2 as usize);
451 let return_types1 = &block1.return_types;
452 let return_types2 = &block2.return_types;
453 if block1.jump_to_top || block2.jump_to_top {
454 if block1.jump_to_top {
455 if !block2.jump_to_top && !return_types2.is_empty() {
456 return Err("block types do not match");
457 }
458 } else if !return_types1.is_empty() {
459 return Err("block types do not match");
460 }
461 } else if *return_types1 != *return_types2 {
462 return Err("block types do not match");
463 }
464 Ok(())
465 }
466
check_memory_index( &self, memory_index: u32, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>467 fn check_memory_index(
468 &self,
469 memory_index: u32,
470 resources: &dyn WasmModuleResources,
471 ) -> OperatorValidatorResult<()> {
472 if memory_index as usize >= resources.memories().len() {
473 return Err("no linear memories are present");
474 }
475 Ok(())
476 }
477
check_shared_memory_index( &self, memory_index: u32, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>478 fn check_shared_memory_index(
479 &self,
480 memory_index: u32,
481 resources: &dyn WasmModuleResources,
482 ) -> OperatorValidatorResult<()> {
483 if memory_index as usize >= resources.memories().len() {
484 return Err("no linear memories are present");
485 }
486 if !resources.memories()[memory_index as usize].shared {
487 return Err("atomic accesses require shared memory");
488 }
489 Ok(())
490 }
491
check_memarg( &self, memarg: &MemoryImmediate, max_align: u32, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>492 fn check_memarg(
493 &self,
494 memarg: &MemoryImmediate,
495 max_align: u32,
496 resources: &dyn WasmModuleResources,
497 ) -> OperatorValidatorResult<()> {
498 self.check_memory_index(0, resources)?;
499 let align = memarg.flags;
500 if align > max_align {
501 return Err("align is required to be at most the number of accessed bytes");
502 }
503 Ok(())
504 }
505
506 #[cfg(feature = "deterministic")]
check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()>507 fn check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()> {
508 if !self.config.deterministic_only {
509 return Err("deterministic_only support is not enabled");
510 }
511 Ok(())
512 }
513
514 #[inline(always)]
515 #[cfg(not(feature = "deterministic"))]
check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()>516 fn check_non_deterministic_enabled(&self) -> OperatorValidatorResult<()> {
517 Ok(())
518 }
519
check_threads_enabled(&self) -> OperatorValidatorResult<()>520 fn check_threads_enabled(&self) -> OperatorValidatorResult<()> {
521 if !self.config.enable_threads {
522 return Err("threads support is not enabled");
523 }
524 Ok(())
525 }
526
check_reference_types_enabled(&self) -> OperatorValidatorResult<()>527 fn check_reference_types_enabled(&self) -> OperatorValidatorResult<()> {
528 if !self.config.enable_reference_types {
529 return Err("reference types support is not enabled");
530 }
531 Ok(())
532 }
533
check_simd_enabled(&self) -> OperatorValidatorResult<()>534 fn check_simd_enabled(&self) -> OperatorValidatorResult<()> {
535 if !self.config.enable_simd {
536 return Err("SIMD support is not enabled");
537 }
538 Ok(())
539 }
540
check_bulk_memory_enabled(&self) -> OperatorValidatorResult<()>541 fn check_bulk_memory_enabled(&self) -> OperatorValidatorResult<()> {
542 if !self.config.enable_bulk_memory {
543 return Err("bulk memory support is not enabled");
544 }
545 Ok(())
546 }
547
check_shared_memarg_wo_align( &self, _: &MemoryImmediate, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>548 fn check_shared_memarg_wo_align(
549 &self,
550 _: &MemoryImmediate,
551 resources: &dyn WasmModuleResources,
552 ) -> OperatorValidatorResult<()> {
553 self.check_shared_memory_index(0, resources)?;
554 Ok(())
555 }
556
check_simd_lane_index(&self, index: SIMDLaneIndex, max: u8) -> OperatorValidatorResult<()>557 fn check_simd_lane_index(&self, index: SIMDLaneIndex, max: u8) -> OperatorValidatorResult<()> {
558 if index >= max {
559 return Err("SIMD index out of bounds");
560 }
561 Ok(())
562 }
563
check_block_type( &self, ty: TypeOrFuncType, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<()>564 fn check_block_type(
565 &self,
566 ty: TypeOrFuncType,
567 resources: &dyn WasmModuleResources,
568 ) -> OperatorValidatorResult<()> {
569 match ty {
570 TypeOrFuncType::Type(Type::EmptyBlockType)
571 | TypeOrFuncType::Type(Type::I32)
572 | TypeOrFuncType::Type(Type::I64)
573 | TypeOrFuncType::Type(Type::F32)
574 | TypeOrFuncType::Type(Type::F64) => Ok(()),
575 TypeOrFuncType::Type(Type::V128) => self.check_simd_enabled(),
576 TypeOrFuncType::FuncType(idx) => {
577 let idx = idx as usize;
578 let types = resources.types();
579 if idx >= types.len() {
580 return Err("type index out of bounds");
581 }
582 let ty = &types[idx];
583 if !self.config.enable_multi_value {
584 if ty.returns.len() > 1 {
585 return Err("blocks, loops, and ifs may only return at most one \
586 value when multi-value is not enabled");
587 }
588 if ty.params.len() > 0 {
589 return Err("blocks, loops, and ifs accept no parameters \
590 when multi-value is not enabled");
591 }
592 }
593 Ok(())
594 }
595 _ => Err("invalid block return type"),
596 }
597 }
598
check_block_params( &self, ty: TypeOrFuncType, resources: &dyn WasmModuleResources, skip: usize, ) -> OperatorValidatorResult<()>599 fn check_block_params(
600 &self,
601 ty: TypeOrFuncType,
602 resources: &dyn WasmModuleResources,
603 skip: usize,
604 ) -> OperatorValidatorResult<()> {
605 if let TypeOrFuncType::FuncType(idx) = ty {
606 let func_ty = &resources.types()[idx as usize];
607 let len = func_ty.params.len();
608 self.check_frame_size(len + skip)?;
609 for i in 0..len {
610 if !self
611 .func_state
612 .assert_stack_type_at(len - 1 - i + skip, func_ty.params[i])
613 {
614 return Err("stack operand type mismatch for block");
615 }
616 }
617 }
618 Ok(())
619 }
620
check_select(&self) -> OperatorValidatorResult<Option<Type>>621 fn check_select(&self) -> OperatorValidatorResult<Option<Type>> {
622 self.check_frame_size(3)?;
623 let func_state = &self.func_state;
624 let last_block = func_state.last_block();
625 Ok(if last_block.is_stack_polymorphic() {
626 match func_state.stack_types.len() - last_block.stack_starts_at {
627 0 => None,
628 1 => {
629 self.check_operands_1(Type::I32)?;
630 None
631 }
632 2 => {
633 self.check_operands_1(Type::I32)?;
634 Some(func_state.stack_types[func_state.stack_types.len() - 2])
635 }
636 _ => {
637 let ty = func_state.stack_types[func_state.stack_types.len() - 3];
638 self.check_operands_2(ty, Type::I32)?;
639 Some(ty)
640 }
641 }
642 } else {
643 let ty = func_state.stack_types[func_state.stack_types.len() - 3];
644 self.check_operands_2(ty, Type::I32)?;
645 Some(ty)
646 })
647 }
648
process_operator( &mut self, operator: &Operator, resources: &dyn WasmModuleResources, ) -> OperatorValidatorResult<FunctionEnd>649 pub(crate) fn process_operator(
650 &mut self,
651 operator: &Operator,
652 resources: &dyn WasmModuleResources,
653 ) -> OperatorValidatorResult<FunctionEnd> {
654 if self.func_state.end_function {
655 return Err("unexpected operator");
656 }
657 match *operator {
658 Operator::Unreachable => self.func_state.start_dead_code(),
659 Operator::Nop => (),
660 Operator::Block { ty } => {
661 self.check_block_type(ty, resources)?;
662 self.check_block_params(ty, resources, 0)?;
663 self.func_state
664 .push_block(ty, BlockType::Block, resources)?;
665 }
666 Operator::Loop { ty } => {
667 self.check_block_type(ty, resources)?;
668 self.check_block_params(ty, resources, 0)?;
669 self.func_state.push_block(ty, BlockType::Loop, resources)?;
670 }
671 Operator::If { ty } => {
672 self.check_block_type(ty, resources)?;
673 self.check_operands_1(Type::I32)?;
674 self.check_block_params(ty, resources, 1)?;
675 self.func_state.push_block(ty, BlockType::If, resources)?;
676 }
677 Operator::Else => {
678 if !self.func_state.last_block().is_else_allowed {
679 return Err("unexpected else: if block is not started");
680 }
681 self.check_block_return()?;
682 self.func_state.reset_block()
683 }
684 Operator::End => {
685 self.check_block_return()?;
686 if self.func_state.blocks.len() == 1 {
687 self.func_state.end_function();
688 return Ok(FunctionEnd::Yes);
689 }
690 if {
691 let last_block = &self.func_state.last_block();
692 last_block.is_else_allowed && !last_block.return_types.is_empty()
693 } {
694 return Err("else is expected: if block has type");
695 }
696 self.func_state.pop_block()
697 }
698 Operator::Br { relative_depth } => {
699 self.check_jump_from_block(relative_depth, 0)?;
700 self.func_state.start_dead_code()
701 }
702 Operator::BrIf { relative_depth } => {
703 self.check_operands_1(Type::I32)?;
704 self.check_jump_from_block(relative_depth, 1)?;
705 if self.func_state.last_block().is_stack_polymorphic() {
706 self.func_state
707 .change_frame_to_exact_types_from(relative_depth as usize)?;
708 } else {
709 self.func_state.change_frame(1)?;
710 }
711 }
712 Operator::BrTable { ref table } => {
713 self.check_operands_1(Type::I32)?;
714 let mut depth0: Option<u32> = None;
715 for relative_depth in table {
716 if depth0.is_none() {
717 self.check_jump_from_block(relative_depth, 1)?;
718 depth0 = Some(relative_depth);
719 continue;
720 }
721 self.match_block_return(relative_depth, depth0.unwrap())?;
722 }
723 self.func_state.start_dead_code()
724 }
725 Operator::Return => {
726 let depth = (self.func_state.blocks.len() - 1) as u32;
727 self.check_jump_from_block(depth, 0)?;
728 self.func_state.start_dead_code()
729 }
730 Operator::Call { function_index } => {
731 if function_index as usize >= resources.func_type_indices().len() {
732 return Err("function index out of bounds");
733 }
734 let type_index = resources.func_type_indices()[function_index as usize];
735 let ty = &resources.types()[type_index as usize];
736 self.check_operands(&ty.params)?;
737 self.func_state
738 .change_frame_with_types(ty.params.len(), &ty.returns)?;
739 }
740 Operator::CallIndirect { index, table_index } => {
741 if table_index as usize >= resources.tables().len() {
742 return Err("table index out of bounds");
743 }
744 if index as usize >= resources.types().len() {
745 return Err("type index out of bounds");
746 }
747 let ty = &resources.types()[index as usize];
748 let mut types = Vec::with_capacity(ty.params.len() + 1);
749 types.extend_from_slice(&ty.params);
750 types.push(Type::I32);
751 self.check_operands(&types)?;
752 self.func_state
753 .change_frame_with_types(ty.params.len() + 1, &ty.returns)?;
754 }
755 Operator::Drop => {
756 self.check_frame_size(1)?;
757 self.func_state.change_frame(1)?;
758 }
759 Operator::Select => {
760 let ty = self.check_select()?;
761 self.func_state.change_frame_after_select(ty)?;
762 }
763 Operator::GetLocal { local_index } => {
764 if local_index as usize >= self.func_state.local_types.len() {
765 return Err("local index out of bounds");
766 }
767 let local_type = self.func_state.local_types[local_index as usize];
768 self.func_state.change_frame_with_type(0, local_type)?;
769 }
770 Operator::SetLocal { local_index } => {
771 if local_index as usize >= self.func_state.local_types.len() {
772 return Err("local index out of bounds");
773 }
774 let local_type = self.func_state.local_types[local_index as usize];
775 self.check_operands_1(local_type)?;
776 self.func_state.change_frame(1)?;
777 }
778 Operator::TeeLocal { local_index } => {
779 if local_index as usize >= self.func_state.local_types.len() {
780 return Err("local index out of bounds");
781 }
782 let local_type = self.func_state.local_types[local_index as usize];
783 self.check_operands_1(local_type)?;
784 self.func_state.change_frame_with_type(1, local_type)?;
785 }
786 Operator::GetGlobal { global_index } => {
787 if global_index as usize >= resources.globals().len() {
788 return Err("global index out of bounds");
789 }
790 let ty = &resources.globals()[global_index as usize];
791 self.func_state.change_frame_with_type(0, ty.content_type)?;
792 }
793 Operator::SetGlobal { global_index } => {
794 if global_index as usize >= resources.globals().len() {
795 return Err("global index out of bounds");
796 }
797 let ty = &resources.globals()[global_index as usize];
798 if !ty.mutable {
799 return Err("global expected to be mutable");
800 }
801 self.check_operands_1(ty.content_type)?;
802 self.func_state.change_frame(1)?;
803 }
804 Operator::I32Load { ref memarg } => {
805 self.check_memarg(memarg, 2, resources)?;
806 self.check_operands_1(Type::I32)?;
807 self.func_state.change_frame_with_type(1, Type::I32)?;
808 }
809 Operator::I64Load { ref memarg } => {
810 self.check_memarg(memarg, 3, resources)?;
811 self.check_operands_1(Type::I32)?;
812 self.func_state.change_frame_with_type(1, Type::I64)?;
813 }
814 Operator::F32Load { ref memarg } => {
815 self.check_non_deterministic_enabled()?;
816 self.check_memarg(memarg, 2, resources)?;
817 self.check_operands_1(Type::I32)?;
818 self.func_state.change_frame_with_type(1, Type::F32)?;
819 }
820 Operator::F64Load { ref memarg } => {
821 self.check_non_deterministic_enabled()?;
822 self.check_memarg(memarg, 3, resources)?;
823 self.check_operands_1(Type::I32)?;
824 self.func_state.change_frame_with_type(1, Type::F64)?;
825 }
826 Operator::I32Load8S { ref memarg } => {
827 self.check_memarg(memarg, 0, resources)?;
828 self.check_operands_1(Type::I32)?;
829 self.func_state.change_frame_with_type(1, Type::I32)?;
830 }
831 Operator::I32Load8U { ref memarg } => {
832 self.check_memarg(memarg, 0, resources)?;
833 self.check_operands_1(Type::I32)?;
834 self.func_state.change_frame_with_type(1, Type::I32)?;
835 }
836 Operator::I32Load16S { ref memarg } => {
837 self.check_memarg(memarg, 1, resources)?;
838 self.check_operands_1(Type::I32)?;
839 self.func_state.change_frame_with_type(1, Type::I32)?;
840 }
841 Operator::I32Load16U { ref memarg } => {
842 self.check_memarg(memarg, 1, resources)?;
843 self.check_operands_1(Type::I32)?;
844 self.func_state.change_frame_with_type(1, Type::I32)?;
845 }
846 Operator::I64Load8S { ref memarg } => {
847 self.check_memarg(memarg, 0, resources)?;
848 self.check_operands_1(Type::I32)?;
849 self.func_state.change_frame_with_type(1, Type::I64)?;
850 }
851 Operator::I64Load8U { ref memarg } => {
852 self.check_memarg(memarg, 0, resources)?;
853 self.check_operands_1(Type::I32)?;
854 self.func_state.change_frame_with_type(1, Type::I64)?;
855 }
856 Operator::I64Load16S { ref memarg } => {
857 self.check_memarg(memarg, 1, resources)?;
858 self.check_operands_1(Type::I32)?;
859 self.func_state.change_frame_with_type(1, Type::I64)?;
860 }
861 Operator::I64Load16U { ref memarg } => {
862 self.check_memarg(memarg, 1, resources)?;
863 self.check_operands_1(Type::I32)?;
864 self.func_state.change_frame_with_type(1, Type::I64)?;
865 }
866 Operator::I64Load32S { ref memarg } => {
867 self.check_memarg(memarg, 2, resources)?;
868 self.check_operands_1(Type::I32)?;
869 self.func_state.change_frame_with_type(1, Type::I64)?;
870 }
871 Operator::I64Load32U { ref memarg } => {
872 self.check_memarg(memarg, 2, resources)?;
873 self.check_operands_1(Type::I32)?;
874 self.func_state.change_frame_with_type(1, Type::I64)?;
875 }
876 Operator::I32Store { ref memarg } => {
877 self.check_memarg(memarg, 2, resources)?;
878 self.check_operands_2(Type::I32, Type::I32)?;
879 self.func_state.change_frame(2)?;
880 }
881 Operator::I64Store { ref memarg } => {
882 self.check_memarg(memarg, 3, resources)?;
883 self.check_operands_2(Type::I32, Type::I64)?;
884 self.func_state.change_frame(2)?;
885 }
886 Operator::F32Store { ref memarg } => {
887 self.check_non_deterministic_enabled()?;
888 self.check_memarg(memarg, 2, resources)?;
889 self.check_operands_2(Type::I32, Type::F32)?;
890 self.func_state.change_frame(2)?;
891 }
892 Operator::F64Store { ref memarg } => {
893 self.check_non_deterministic_enabled()?;
894 self.check_memarg(memarg, 3, resources)?;
895 self.check_operands_2(Type::I32, Type::F64)?;
896 self.func_state.change_frame(2)?;
897 }
898 Operator::I32Store8 { ref memarg } => {
899 self.check_memarg(memarg, 0, resources)?;
900 self.check_operands_2(Type::I32, Type::I32)?;
901 self.func_state.change_frame(2)?;
902 }
903 Operator::I32Store16 { ref memarg } => {
904 self.check_memarg(memarg, 1, resources)?;
905 self.check_operands_2(Type::I32, Type::I32)?;
906 self.func_state.change_frame(2)?;
907 }
908 Operator::I64Store8 { ref memarg } => {
909 self.check_memarg(memarg, 0, resources)?;
910 self.check_operands_2(Type::I32, Type::I64)?;
911 self.func_state.change_frame(2)?;
912 }
913 Operator::I64Store16 { ref memarg } => {
914 self.check_memarg(memarg, 1, resources)?;
915 self.check_operands_2(Type::I32, Type::I64)?;
916 self.func_state.change_frame(2)?;
917 }
918 Operator::I64Store32 { ref memarg } => {
919 self.check_memarg(memarg, 2, resources)?;
920 self.check_operands_2(Type::I32, Type::I64)?;
921 self.func_state.change_frame(2)?;
922 }
923 Operator::MemorySize {
924 reserved: memory_index,
925 } => {
926 self.check_memory_index(memory_index, resources)?;
927 self.func_state.change_frame_with_type(0, Type::I32)?;
928 }
929 Operator::MemoryGrow {
930 reserved: memory_index,
931 } => {
932 self.check_memory_index(memory_index, resources)?;
933 self.check_operands_1(Type::I32)?;
934 self.func_state.change_frame_with_type(1, Type::I32)?;
935 }
936 Operator::I32Const { .. } => self.func_state.change_frame_with_type(0, Type::I32)?,
937 Operator::I64Const { .. } => self.func_state.change_frame_with_type(0, Type::I64)?,
938 Operator::F32Const { .. } => {
939 self.check_non_deterministic_enabled()?;
940 self.func_state.change_frame_with_type(0, Type::F32)?;
941 }
942 Operator::F64Const { .. } => {
943 self.check_non_deterministic_enabled()?;
944 self.func_state.change_frame_with_type(0, Type::F64)?;
945 }
946 Operator::I32Eqz => {
947 self.check_operands_1(Type::I32)?;
948 self.func_state.change_frame_with_type(1, Type::I32)?;
949 }
950 Operator::I32Eq
951 | Operator::I32Ne
952 | Operator::I32LtS
953 | Operator::I32LtU
954 | Operator::I32GtS
955 | Operator::I32GtU
956 | Operator::I32LeS
957 | Operator::I32LeU
958 | Operator::I32GeS
959 | Operator::I32GeU => {
960 self.check_operands_2(Type::I32, Type::I32)?;
961 self.func_state.change_frame_with_type(2, Type::I32)?;
962 }
963 Operator::I64Eqz => {
964 self.check_operands_1(Type::I64)?;
965 self.func_state.change_frame_with_type(1, Type::I32)?;
966 }
967 Operator::I64Eq
968 | Operator::I64Ne
969 | Operator::I64LtS
970 | Operator::I64LtU
971 | Operator::I64GtS
972 | Operator::I64GtU
973 | Operator::I64LeS
974 | Operator::I64LeU
975 | Operator::I64GeS
976 | Operator::I64GeU => {
977 self.check_operands_2(Type::I64, Type::I64)?;
978 self.func_state.change_frame_with_type(2, Type::I32)?;
979 }
980 Operator::F32Eq
981 | Operator::F32Ne
982 | Operator::F32Lt
983 | Operator::F32Gt
984 | Operator::F32Le
985 | Operator::F32Ge => {
986 self.check_non_deterministic_enabled()?;
987 self.check_operands_2(Type::F32, Type::F32)?;
988 self.func_state.change_frame_with_type(2, Type::I32)?;
989 }
990 Operator::F64Eq
991 | Operator::F64Ne
992 | Operator::F64Lt
993 | Operator::F64Gt
994 | Operator::F64Le
995 | Operator::F64Ge => {
996 self.check_non_deterministic_enabled()?;
997 self.check_operands_2(Type::F64, Type::F64)?;
998 self.func_state.change_frame_with_type(2, Type::I32)?;
999 }
1000 Operator::I32Clz | Operator::I32Ctz | Operator::I32Popcnt => {
1001 self.check_operands_1(Type::I32)?;
1002 self.func_state.change_frame_with_type(1, Type::I32)?;
1003 }
1004 Operator::I32Add
1005 | Operator::I32Sub
1006 | Operator::I32Mul
1007 | Operator::I32DivS
1008 | Operator::I32DivU
1009 | Operator::I32RemS
1010 | Operator::I32RemU
1011 | Operator::I32And
1012 | Operator::I32Or
1013 | Operator::I32Xor
1014 | Operator::I32Shl
1015 | Operator::I32ShrS
1016 | Operator::I32ShrU
1017 | Operator::I32Rotl
1018 | Operator::I32Rotr => {
1019 self.check_operands_2(Type::I32, Type::I32)?;
1020 self.func_state.change_frame_with_type(2, Type::I32)?;
1021 }
1022 Operator::I64Clz | Operator::I64Ctz | Operator::I64Popcnt => {
1023 self.check_operands_1(Type::I64)?;
1024 self.func_state.change_frame_with_type(1, Type::I64)?;
1025 }
1026 Operator::I64Add
1027 | Operator::I64Sub
1028 | Operator::I64Mul
1029 | Operator::I64DivS
1030 | Operator::I64DivU
1031 | Operator::I64RemS
1032 | Operator::I64RemU
1033 | Operator::I64And
1034 | Operator::I64Or
1035 | Operator::I64Xor
1036 | Operator::I64Shl
1037 | Operator::I64ShrS
1038 | Operator::I64ShrU
1039 | Operator::I64Rotl
1040 | Operator::I64Rotr => {
1041 self.check_operands_2(Type::I64, Type::I64)?;
1042 self.func_state.change_frame_with_type(2, Type::I64)?;
1043 }
1044 Operator::F32Abs
1045 | Operator::F32Neg
1046 | Operator::F32Ceil
1047 | Operator::F32Floor
1048 | Operator::F32Trunc
1049 | Operator::F32Nearest
1050 | Operator::F32Sqrt => {
1051 self.check_non_deterministic_enabled()?;
1052 self.check_operands_1(Type::F32)?;
1053 self.func_state.change_frame_with_type(1, Type::F32)?;
1054 }
1055 Operator::F32Add
1056 | Operator::F32Sub
1057 | Operator::F32Mul
1058 | Operator::F32Div
1059 | Operator::F32Min
1060 | Operator::F32Max
1061 | Operator::F32Copysign => {
1062 self.check_non_deterministic_enabled()?;
1063 self.check_operands_2(Type::F32, Type::F32)?;
1064 self.func_state.change_frame_with_type(2, Type::F32)?;
1065 }
1066 Operator::F64Abs
1067 | Operator::F64Neg
1068 | Operator::F64Ceil
1069 | Operator::F64Floor
1070 | Operator::F64Trunc
1071 | Operator::F64Nearest
1072 | Operator::F64Sqrt => {
1073 self.check_non_deterministic_enabled()?;
1074 self.check_operands_1(Type::F64)?;
1075 self.func_state.change_frame_with_type(1, Type::F64)?;
1076 }
1077 Operator::F64Add
1078 | Operator::F64Sub
1079 | Operator::F64Mul
1080 | Operator::F64Div
1081 | Operator::F64Min
1082 | Operator::F64Max
1083 | Operator::F64Copysign => {
1084 self.check_non_deterministic_enabled()?;
1085 self.check_operands_2(Type::F64, Type::F64)?;
1086 self.func_state.change_frame_with_type(2, Type::F64)?;
1087 }
1088 Operator::I32WrapI64 => {
1089 self.check_operands_1(Type::I64)?;
1090 self.func_state.change_frame_with_type(1, Type::I32)?;
1091 }
1092 Operator::I32TruncSF32 | Operator::I32TruncUF32 => {
1093 self.check_operands_1(Type::F32)?;
1094 self.func_state.change_frame_with_type(1, Type::I32)?;
1095 }
1096 Operator::I32TruncSF64 | Operator::I32TruncUF64 => {
1097 self.check_operands_1(Type::F64)?;
1098 self.func_state.change_frame_with_type(1, Type::I32)?;
1099 }
1100 Operator::I64ExtendSI32 | Operator::I64ExtendUI32 => {
1101 self.check_operands_1(Type::I32)?;
1102 self.func_state.change_frame_with_type(1, Type::I64)?;
1103 }
1104 Operator::I64TruncSF32 | Operator::I64TruncUF32 => {
1105 self.check_operands_1(Type::F32)?;
1106 self.func_state.change_frame_with_type(1, Type::I64)?;
1107 }
1108 Operator::I64TruncSF64 | Operator::I64TruncUF64 => {
1109 self.check_operands_1(Type::F64)?;
1110 self.func_state.change_frame_with_type(1, Type::I64)?;
1111 }
1112 Operator::F32ConvertSI32 | Operator::F32ConvertUI32 => {
1113 self.check_non_deterministic_enabled()?;
1114 self.check_operands_1(Type::I32)?;
1115 self.func_state.change_frame_with_type(1, Type::F32)?;
1116 }
1117 Operator::F32ConvertSI64 | Operator::F32ConvertUI64 => {
1118 self.check_non_deterministic_enabled()?;
1119 self.check_operands_1(Type::I64)?;
1120 self.func_state.change_frame_with_type(1, Type::F32)?;
1121 }
1122 Operator::F32DemoteF64 => {
1123 self.check_non_deterministic_enabled()?;
1124 self.check_operands_1(Type::F64)?;
1125 self.func_state.change_frame_with_type(1, Type::F32)?;
1126 }
1127 Operator::F64ConvertSI32 | Operator::F64ConvertUI32 => {
1128 self.check_non_deterministic_enabled()?;
1129 self.check_operands_1(Type::I32)?;
1130 self.func_state.change_frame_with_type(1, Type::F64)?;
1131 }
1132 Operator::F64ConvertSI64 | Operator::F64ConvertUI64 => {
1133 self.check_non_deterministic_enabled()?;
1134 self.check_operands_1(Type::I64)?;
1135 self.func_state.change_frame_with_type(1, Type::F64)?;
1136 }
1137 Operator::F64PromoteF32 => {
1138 self.check_non_deterministic_enabled()?;
1139 self.check_operands_1(Type::F32)?;
1140 self.func_state.change_frame_with_type(1, Type::F64)?;
1141 }
1142 Operator::I32ReinterpretF32 => {
1143 self.check_operands_1(Type::F32)?;
1144 self.func_state.change_frame_with_type(1, Type::I32)?;
1145 }
1146 Operator::I64ReinterpretF64 => {
1147 self.check_operands_1(Type::F64)?;
1148 self.func_state.change_frame_with_type(1, Type::I64)?;
1149 }
1150 Operator::F32ReinterpretI32 => {
1151 self.check_non_deterministic_enabled()?;
1152 self.check_operands_1(Type::I32)?;
1153 self.func_state.change_frame_with_type(1, Type::F32)?;
1154 }
1155 Operator::F64ReinterpretI64 => {
1156 self.check_non_deterministic_enabled()?;
1157 self.check_operands_1(Type::I64)?;
1158 self.func_state.change_frame_with_type(1, Type::F64)?;
1159 }
1160 Operator::I32TruncSSatF32 | Operator::I32TruncUSatF32 => {
1161 self.check_operands_1(Type::F32)?;
1162 self.func_state.change_frame_with_type(1, Type::I32)?;
1163 }
1164 Operator::I32TruncSSatF64 | Operator::I32TruncUSatF64 => {
1165 self.check_operands_1(Type::F64)?;
1166 self.func_state.change_frame_with_type(1, Type::I32)?;
1167 }
1168 Operator::I64TruncSSatF32 | Operator::I64TruncUSatF32 => {
1169 self.check_operands_1(Type::F32)?;
1170 self.func_state.change_frame_with_type(1, Type::I64)?;
1171 }
1172 Operator::I64TruncSSatF64 | Operator::I64TruncUSatF64 => {
1173 self.check_operands_1(Type::F64)?;
1174 self.func_state.change_frame_with_type(1, Type::I64)?;
1175 }
1176 Operator::I32Extend16S | Operator::I32Extend8S => {
1177 self.check_operands_1(Type::I32)?;
1178 self.func_state.change_frame_with_type(1, Type::I32)?;
1179 }
1180
1181 Operator::I64Extend32S | Operator::I64Extend16S | Operator::I64Extend8S => {
1182 self.check_operands_1(Type::I64)?;
1183 self.func_state.change_frame_with_type(1, Type::I64)?;
1184 }
1185
1186 Operator::I32AtomicLoad { ref memarg }
1187 | Operator::I32AtomicLoad16U { ref memarg }
1188 | Operator::I32AtomicLoad8U { ref memarg } => {
1189 self.check_threads_enabled()?;
1190 self.check_shared_memarg_wo_align(memarg, resources)?;
1191 self.check_operands_1(Type::I32)?;
1192 self.func_state.change_frame_with_type(1, Type::I32)?;
1193 }
1194 Operator::I64AtomicLoad { ref memarg }
1195 | Operator::I64AtomicLoad32U { ref memarg }
1196 | Operator::I64AtomicLoad16U { ref memarg }
1197 | Operator::I64AtomicLoad8U { ref memarg } => {
1198 self.check_threads_enabled()?;
1199 self.check_shared_memarg_wo_align(memarg, resources)?;
1200 self.check_operands_1(Type::I32)?;
1201 self.func_state.change_frame_with_type(1, Type::I64)?;
1202 }
1203 Operator::I32AtomicStore { ref memarg }
1204 | Operator::I32AtomicStore16 { ref memarg }
1205 | Operator::I32AtomicStore8 { ref memarg } => {
1206 self.check_threads_enabled()?;
1207 self.check_shared_memarg_wo_align(memarg, resources)?;
1208 self.check_operands_2(Type::I32, Type::I32)?;
1209 self.func_state.change_frame(2)?;
1210 }
1211 Operator::I64AtomicStore { ref memarg }
1212 | Operator::I64AtomicStore32 { ref memarg }
1213 | Operator::I64AtomicStore16 { ref memarg }
1214 | Operator::I64AtomicStore8 { ref memarg } => {
1215 self.check_threads_enabled()?;
1216 self.check_shared_memarg_wo_align(memarg, resources)?;
1217 self.check_operands_2(Type::I32, Type::I64)?;
1218 self.func_state.change_frame(2)?;
1219 }
1220 Operator::I32AtomicRmwAdd { ref memarg }
1221 | Operator::I32AtomicRmwSub { ref memarg }
1222 | Operator::I32AtomicRmwAnd { ref memarg }
1223 | Operator::I32AtomicRmwOr { ref memarg }
1224 | Operator::I32AtomicRmwXor { ref memarg }
1225 | Operator::I32AtomicRmw16UAdd { ref memarg }
1226 | Operator::I32AtomicRmw16USub { ref memarg }
1227 | Operator::I32AtomicRmw16UAnd { ref memarg }
1228 | Operator::I32AtomicRmw16UOr { ref memarg }
1229 | Operator::I32AtomicRmw16UXor { ref memarg }
1230 | Operator::I32AtomicRmw8UAdd { ref memarg }
1231 | Operator::I32AtomicRmw8USub { ref memarg }
1232 | Operator::I32AtomicRmw8UAnd { ref memarg }
1233 | Operator::I32AtomicRmw8UOr { ref memarg }
1234 | Operator::I32AtomicRmw8UXor { ref memarg } => {
1235 self.check_threads_enabled()?;
1236 self.check_shared_memarg_wo_align(memarg, resources)?;
1237 self.check_operands_2(Type::I32, Type::I32)?;
1238 self.func_state.change_frame_with_type(2, Type::I32)?;
1239 }
1240 Operator::I64AtomicRmwAdd { ref memarg }
1241 | Operator::I64AtomicRmwSub { ref memarg }
1242 | Operator::I64AtomicRmwAnd { ref memarg }
1243 | Operator::I64AtomicRmwOr { ref memarg }
1244 | Operator::I64AtomicRmwXor { ref memarg }
1245 | Operator::I64AtomicRmw32UAdd { ref memarg }
1246 | Operator::I64AtomicRmw32USub { ref memarg }
1247 | Operator::I64AtomicRmw32UAnd { ref memarg }
1248 | Operator::I64AtomicRmw32UOr { ref memarg }
1249 | Operator::I64AtomicRmw32UXor { ref memarg }
1250 | Operator::I64AtomicRmw16UAdd { ref memarg }
1251 | Operator::I64AtomicRmw16USub { ref memarg }
1252 | Operator::I64AtomicRmw16UAnd { ref memarg }
1253 | Operator::I64AtomicRmw16UOr { ref memarg }
1254 | Operator::I64AtomicRmw16UXor { ref memarg }
1255 | Operator::I64AtomicRmw8UAdd { ref memarg }
1256 | Operator::I64AtomicRmw8USub { ref memarg }
1257 | Operator::I64AtomicRmw8UAnd { ref memarg }
1258 | Operator::I64AtomicRmw8UOr { ref memarg }
1259 | Operator::I64AtomicRmw8UXor { ref memarg } => {
1260 self.check_threads_enabled()?;
1261 self.check_shared_memarg_wo_align(memarg, resources)?;
1262 self.check_operands_2(Type::I32, Type::I64)?;
1263 self.func_state.change_frame_with_type(2, Type::I64)?;
1264 }
1265 Operator::I32AtomicRmwXchg { ref memarg }
1266 | Operator::I32AtomicRmw16UXchg { ref memarg }
1267 | Operator::I32AtomicRmw8UXchg { ref memarg } => {
1268 self.check_threads_enabled()?;
1269 self.check_shared_memarg_wo_align(memarg, resources)?;
1270 self.check_operands_2(Type::I32, Type::I32)?;
1271 self.func_state.change_frame_with_type(2, Type::I32)?;
1272 }
1273 Operator::I32AtomicRmwCmpxchg { ref memarg }
1274 | Operator::I32AtomicRmw16UCmpxchg { ref memarg }
1275 | Operator::I32AtomicRmw8UCmpxchg { ref memarg } => {
1276 self.check_threads_enabled()?;
1277 self.check_shared_memarg_wo_align(memarg, resources)?;
1278 self.check_operands(&[Type::I32, Type::I32, Type::I32])?;
1279 self.func_state.change_frame_with_type(3, Type::I32)?;
1280 }
1281 Operator::I64AtomicRmwXchg { ref memarg }
1282 | Operator::I64AtomicRmw32UXchg { ref memarg }
1283 | Operator::I64AtomicRmw16UXchg { ref memarg }
1284 | Operator::I64AtomicRmw8UXchg { ref memarg } => {
1285 self.check_threads_enabled()?;
1286 self.check_shared_memarg_wo_align(memarg, resources)?;
1287 self.check_operands_2(Type::I32, Type::I64)?;
1288 self.func_state.change_frame_with_type(2, Type::I64)?;
1289 }
1290 Operator::I64AtomicRmwCmpxchg { ref memarg }
1291 | Operator::I64AtomicRmw32UCmpxchg { ref memarg }
1292 | Operator::I64AtomicRmw16UCmpxchg { ref memarg }
1293 | Operator::I64AtomicRmw8UCmpxchg { ref memarg } => {
1294 self.check_threads_enabled()?;
1295 self.check_shared_memarg_wo_align(memarg, resources)?;
1296 self.check_operands(&[Type::I32, Type::I64, Type::I64])?;
1297 self.func_state.change_frame_with_type(3, Type::I64)?;
1298 }
1299 Operator::Wake { ref memarg } => {
1300 self.check_threads_enabled()?;
1301 self.check_shared_memarg_wo_align(memarg, resources)?;
1302 self.check_operands_2(Type::I32, Type::I32)?;
1303 self.func_state.change_frame_with_type(2, Type::I32)?;
1304 }
1305 Operator::I32Wait { ref memarg } => {
1306 self.check_threads_enabled()?;
1307 self.check_shared_memarg_wo_align(memarg, resources)?;
1308 self.check_operands(&[Type::I32, Type::I32, Type::I64])?;
1309 self.func_state.change_frame_with_type(3, Type::I32)?;
1310 }
1311 Operator::I64Wait { ref memarg } => {
1312 self.check_threads_enabled()?;
1313 self.check_shared_memarg_wo_align(memarg, resources)?;
1314 self.check_operands(&[Type::I32, Type::I64, Type::I64])?;
1315 self.func_state.change_frame_with_type(3, Type::I32)?;
1316 }
1317 Operator::Fence { ref flags } => {
1318 self.check_threads_enabled()?;
1319 if *flags != 0 {
1320 return Err("non-zero flags for fence not supported yet");
1321 }
1322 }
1323 Operator::RefNull => {
1324 self.check_reference_types_enabled()?;
1325 self.func_state.change_frame_with_type(0, Type::Null)?;
1326 }
1327 Operator::RefIsNull => {
1328 self.check_reference_types_enabled()?;
1329 self.check_operands(&[Type::AnyRef])?;
1330 self.func_state.change_frame_with_type(1, Type::I32)?;
1331 }
1332 Operator::V128Load { ref memarg } => {
1333 self.check_simd_enabled()?;
1334 self.check_memarg(memarg, 4, resources)?;
1335 self.check_operands_1(Type::I32)?;
1336 self.func_state.change_frame_with_type(1, Type::V128)?;
1337 }
1338 Operator::V128Store { ref memarg } => {
1339 self.check_simd_enabled()?;
1340 self.check_memarg(memarg, 4, resources)?;
1341 self.check_operands_2(Type::I32, Type::V128)?;
1342 self.func_state.change_frame(2)?;
1343 }
1344 Operator::V128Const { .. } => {
1345 self.check_simd_enabled()?;
1346 self.func_state.change_frame_with_type(0, Type::V128)?;
1347 }
1348 Operator::I8x16Splat | Operator::I16x8Splat | Operator::I32x4Splat => {
1349 self.check_simd_enabled()?;
1350 self.check_operands_1(Type::I32)?;
1351 self.func_state.change_frame_with_type(1, Type::V128)?;
1352 }
1353 Operator::I64x2Splat => {
1354 self.check_simd_enabled()?;
1355 self.check_operands_1(Type::I64)?;
1356 self.func_state.change_frame_with_type(1, Type::V128)?;
1357 }
1358 Operator::F32x4Splat => {
1359 self.check_non_deterministic_enabled()?;
1360 self.check_simd_enabled()?;
1361 self.check_operands_1(Type::F32)?;
1362 self.func_state.change_frame_with_type(1, Type::V128)?;
1363 }
1364 Operator::F64x2Splat => {
1365 self.check_non_deterministic_enabled()?;
1366 self.check_simd_enabled()?;
1367 self.check_operands_1(Type::F64)?;
1368 self.func_state.change_frame_with_type(1, Type::V128)?;
1369 }
1370 Operator::I8x16ExtractLaneS { lane } | Operator::I8x16ExtractLaneU { lane } => {
1371 self.check_simd_enabled()?;
1372 self.check_simd_lane_index(lane, 16)?;
1373 self.check_operands_1(Type::V128)?;
1374 self.func_state.change_frame_with_type(1, Type::I32)?;
1375 }
1376 Operator::I16x8ExtractLaneS { lane } | Operator::I16x8ExtractLaneU { lane } => {
1377 self.check_simd_enabled()?;
1378 self.check_simd_lane_index(lane, 8)?;
1379 self.check_operands_1(Type::V128)?;
1380 self.func_state.change_frame_with_type(1, Type::I32)?;
1381 }
1382 Operator::I32x4ExtractLane { lane } => {
1383 self.check_simd_enabled()?;
1384 self.check_simd_lane_index(lane, 4)?;
1385 self.check_operands_1(Type::V128)?;
1386 self.func_state.change_frame_with_type(1, Type::I32)?;
1387 }
1388 Operator::I8x16ReplaceLane { lane } => {
1389 self.check_simd_enabled()?;
1390 self.check_simd_lane_index(lane, 16)?;
1391 self.check_operands_2(Type::V128, Type::I32)?;
1392 self.func_state.change_frame_with_type(2, Type::V128)?;
1393 }
1394 Operator::I16x8ReplaceLane { lane } => {
1395 self.check_simd_enabled()?;
1396 self.check_simd_lane_index(lane, 8)?;
1397 self.check_operands_2(Type::V128, Type::I32)?;
1398 self.func_state.change_frame_with_type(2, Type::V128)?;
1399 }
1400 Operator::I32x4ReplaceLane { lane } => {
1401 self.check_simd_enabled()?;
1402 self.check_simd_lane_index(lane, 4)?;
1403 self.check_operands_2(Type::V128, Type::I32)?;
1404 self.func_state.change_frame_with_type(2, Type::V128)?;
1405 }
1406 Operator::I64x2ExtractLane { lane } => {
1407 self.check_simd_enabled()?;
1408 self.check_simd_lane_index(lane, 2)?;
1409 self.check_operands_1(Type::V128)?;
1410 self.func_state.change_frame_with_type(1, Type::I64)?;
1411 }
1412 Operator::I64x2ReplaceLane { lane } => {
1413 self.check_simd_enabled()?;
1414 self.check_simd_lane_index(lane, 2)?;
1415 self.check_operands_2(Type::V128, Type::I64)?;
1416 self.func_state.change_frame_with_type(2, Type::V128)?;
1417 }
1418 Operator::F32x4ExtractLane { lane } => {
1419 self.check_non_deterministic_enabled()?;
1420 self.check_simd_enabled()?;
1421 self.check_simd_lane_index(lane, 4)?;
1422 self.check_operands_1(Type::V128)?;
1423 self.func_state.change_frame_with_type(1, Type::F32)?;
1424 }
1425 Operator::F32x4ReplaceLane { lane } => {
1426 self.check_non_deterministic_enabled()?;
1427 self.check_simd_enabled()?;
1428 self.check_simd_lane_index(lane, 4)?;
1429 self.check_operands_2(Type::V128, Type::F32)?;
1430 self.func_state.change_frame_with_type(2, Type::V128)?;
1431 }
1432 Operator::F64x2ExtractLane { lane } => {
1433 self.check_non_deterministic_enabled()?;
1434 self.check_simd_enabled()?;
1435 self.check_simd_lane_index(lane, 2)?;
1436 self.check_operands_1(Type::V128)?;
1437 self.func_state.change_frame_with_type(1, Type::F64)?;
1438 }
1439 Operator::F64x2ReplaceLane { lane } => {
1440 self.check_non_deterministic_enabled()?;
1441 self.check_simd_enabled()?;
1442 self.check_simd_lane_index(lane, 2)?;
1443 self.check_operands_2(Type::V128, Type::F64)?;
1444 self.func_state.change_frame_with_type(2, Type::V128)?;
1445 }
1446 Operator::F32x4Eq
1447 | Operator::F32x4Ne
1448 | Operator::F32x4Lt
1449 | Operator::F32x4Gt
1450 | Operator::F32x4Le
1451 | Operator::F32x4Ge
1452 | Operator::F64x2Eq
1453 | Operator::F64x2Ne
1454 | Operator::F64x2Lt
1455 | Operator::F64x2Gt
1456 | Operator::F64x2Le
1457 | Operator::F64x2Ge
1458 | Operator::F32x4Add
1459 | Operator::F32x4Sub
1460 | Operator::F32x4Mul
1461 | Operator::F32x4Div
1462 | Operator::F32x4Min
1463 | Operator::F32x4Max
1464 | Operator::F64x2Add
1465 | Operator::F64x2Sub
1466 | Operator::F64x2Mul
1467 | Operator::F64x2Div
1468 | Operator::F64x2Min
1469 | Operator::F64x2Max => {
1470 self.check_non_deterministic_enabled()?;
1471 self.check_simd_enabled()?;
1472 self.check_operands_2(Type::V128, Type::V128)?;
1473 self.func_state.change_frame_with_type(2, Type::V128)?;
1474 }
1475 Operator::I8x16Eq
1476 | Operator::I8x16Ne
1477 | Operator::I8x16LtS
1478 | Operator::I8x16LtU
1479 | Operator::I8x16GtS
1480 | Operator::I8x16GtU
1481 | Operator::I8x16LeS
1482 | Operator::I8x16LeU
1483 | Operator::I8x16GeS
1484 | Operator::I8x16GeU
1485 | Operator::I16x8Eq
1486 | Operator::I16x8Ne
1487 | Operator::I16x8LtS
1488 | Operator::I16x8LtU
1489 | Operator::I16x8GtS
1490 | Operator::I16x8GtU
1491 | Operator::I16x8LeS
1492 | Operator::I16x8LeU
1493 | Operator::I16x8GeS
1494 | Operator::I16x8GeU
1495 | Operator::I32x4Eq
1496 | Operator::I32x4Ne
1497 | Operator::I32x4LtS
1498 | Operator::I32x4LtU
1499 | Operator::I32x4GtS
1500 | Operator::I32x4GtU
1501 | Operator::I32x4LeS
1502 | Operator::I32x4LeU
1503 | Operator::I32x4GeS
1504 | Operator::I32x4GeU
1505 | Operator::V128And
1506 | Operator::V128Or
1507 | Operator::V128Xor
1508 | Operator::I8x16Add
1509 | Operator::I8x16AddSaturateS
1510 | Operator::I8x16AddSaturateU
1511 | Operator::I8x16Sub
1512 | Operator::I8x16SubSaturateS
1513 | Operator::I8x16SubSaturateU
1514 | Operator::I8x16Mul
1515 | Operator::I16x8Add
1516 | Operator::I16x8AddSaturateS
1517 | Operator::I16x8AddSaturateU
1518 | Operator::I16x8Sub
1519 | Operator::I16x8SubSaturateS
1520 | Operator::I16x8SubSaturateU
1521 | Operator::I16x8Mul
1522 | Operator::I32x4Add
1523 | Operator::I32x4Sub
1524 | Operator::I32x4Mul
1525 | Operator::I64x2Add
1526 | Operator::I64x2Sub => {
1527 self.check_simd_enabled()?;
1528 self.check_operands_2(Type::V128, Type::V128)?;
1529 self.func_state.change_frame_with_type(2, Type::V128)?;
1530 }
1531 Operator::F32x4Abs
1532 | Operator::F32x4Neg
1533 | Operator::F32x4Sqrt
1534 | Operator::F64x2Abs
1535 | Operator::F64x2Neg
1536 | Operator::F64x2Sqrt
1537 | Operator::F32x4ConvertSI32x4
1538 | Operator::F32x4ConvertUI32x4
1539 | Operator::F64x2ConvertSI64x2
1540 | Operator::F64x2ConvertUI64x2 => {
1541 self.check_non_deterministic_enabled()?;
1542 self.check_simd_enabled()?;
1543 self.check_operands_1(Type::V128)?;
1544 self.func_state.change_frame_with_type(1, Type::V128)?;
1545 }
1546 Operator::V128Not
1547 | Operator::I8x16Neg
1548 | Operator::I16x8Neg
1549 | Operator::I32x4Neg
1550 | Operator::I64x2Neg
1551 | Operator::I32x4TruncSF32x4Sat
1552 | Operator::I32x4TruncUF32x4Sat
1553 | Operator::I64x2TruncSF64x2Sat
1554 | Operator::I64x2TruncUF64x2Sat => {
1555 self.check_simd_enabled()?;
1556 self.check_operands_1(Type::V128)?;
1557 self.func_state.change_frame_with_type(1, Type::V128)?;
1558 }
1559 Operator::V128Bitselect => {
1560 self.check_simd_enabled()?;
1561 self.check_operands(&[Type::V128, Type::V128, Type::V128])?;
1562 self.func_state.change_frame_with_type(3, Type::V128)?;
1563 }
1564 Operator::I8x16AnyTrue
1565 | Operator::I8x16AllTrue
1566 | Operator::I16x8AnyTrue
1567 | Operator::I16x8AllTrue
1568 | Operator::I32x4AnyTrue
1569 | Operator::I32x4AllTrue
1570 | Operator::I64x2AnyTrue
1571 | Operator::I64x2AllTrue => {
1572 self.check_simd_enabled()?;
1573 self.check_operands_1(Type::V128)?;
1574 self.func_state.change_frame_with_type(1, Type::I32)?;
1575 }
1576 Operator::I8x16Shl
1577 | Operator::I8x16ShrS
1578 | Operator::I8x16ShrU
1579 | Operator::I16x8Shl
1580 | Operator::I16x8ShrS
1581 | Operator::I16x8ShrU
1582 | Operator::I32x4Shl
1583 | Operator::I32x4ShrS
1584 | Operator::I32x4ShrU
1585 | Operator::I64x2Shl
1586 | Operator::I64x2ShrS
1587 | Operator::I64x2ShrU => {
1588 self.check_simd_enabled()?;
1589 self.check_operands_2(Type::V128, Type::I32)?;
1590 self.func_state.change_frame_with_type(2, Type::V128)?;
1591 }
1592 Operator::V8x16Swizzle => {
1593 self.check_simd_enabled()?;
1594 self.check_operands_2(Type::V128, Type::V128)?;
1595 self.func_state.change_frame_with_type(2, Type::V128)?;
1596 }
1597 Operator::V8x16Shuffle { ref lanes } => {
1598 self.check_simd_enabled()?;
1599 self.check_operands_2(Type::V128, Type::V128)?;
1600 for i in lanes {
1601 self.check_simd_lane_index(*i, 32)?;
1602 }
1603 self.func_state.change_frame_with_type(2, Type::V128)?;
1604 }
1605 Operator::I8x16LoadSplat { ref memarg }
1606 | Operator::I16x8LoadSplat { ref memarg }
1607 | Operator::I32x4LoadSplat { ref memarg }
1608 | Operator::I64x2LoadSplat { ref memarg } => {
1609 self.check_simd_enabled()?;
1610 self.check_memarg(memarg, 4, resources)?;
1611 self.func_state.change_frame_with_type(1, Type::V128)?;
1612 }
1613
1614 Operator::MemoryInit { segment } => {
1615 self.check_bulk_memory_enabled()?;
1616 if segment >= resources.data_count() {
1617 return Err("segment index out of bounds");
1618 }
1619 self.check_memory_index(0, resources)?;
1620 self.check_operands(&[Type::I32, Type::I32, Type::I32])?;
1621 self.func_state.change_frame(3)?;
1622 }
1623 Operator::DataDrop { segment } => {
1624 self.check_bulk_memory_enabled()?;
1625 if segment >= resources.data_count() {
1626 return Err("segment index out of bounds");
1627 }
1628 }
1629 Operator::MemoryCopy | Operator::MemoryFill => {
1630 self.check_bulk_memory_enabled()?;
1631 self.check_memory_index(0, resources)?;
1632 self.check_operands(&[Type::I32, Type::I32, Type::I32])?;
1633 self.func_state.change_frame(3)?;
1634 }
1635 Operator::TableInit { segment } => {
1636 self.check_bulk_memory_enabled()?;
1637 if segment >= resources.element_count() {
1638 return Err("segment index out of bounds");
1639 }
1640 if 0 >= resources.tables().len() {
1641 return Err("table index out of bounds");
1642 }
1643 self.check_operands(&[Type::I32, Type::I32, Type::I32])?;
1644 self.func_state.change_frame(3)?;
1645 }
1646 Operator::ElemDrop { segment } => {
1647 self.check_bulk_memory_enabled()?;
1648 if segment >= resources.element_count() {
1649 return Err("segment index out of bounds");
1650 }
1651 }
1652 Operator::TableCopy => {
1653 self.check_bulk_memory_enabled()?;
1654 if 0 >= resources.tables().len() {
1655 return Err("table index out of bounds");
1656 }
1657 self.check_operands(&[Type::I32, Type::I32, Type::I32])?;
1658 self.func_state.change_frame(3)?;
1659 }
1660 Operator::TableGet { table } => {
1661 self.check_reference_types_enabled()?;
1662 if table as usize >= resources.tables().len() {
1663 return Err("table index out of bounds");
1664 }
1665 self.check_operands(&[Type::I32])?;
1666 self.func_state.change_frame_with_type(1, Type::AnyRef)?;
1667 }
1668 Operator::TableSet { table } => {
1669 self.check_reference_types_enabled()?;
1670 if table as usize >= resources.tables().len() {
1671 return Err("table index out of bounds");
1672 }
1673 self.check_operands(&[Type::I32, Type::AnyRef])?;
1674 self.func_state.change_frame(2)?;
1675 }
1676 Operator::TableGrow { table } => {
1677 self.check_reference_types_enabled()?;
1678 if table as usize >= resources.tables().len() {
1679 return Err("table index out of bounds");
1680 }
1681 self.check_operands(&[Type::I32])?;
1682 self.func_state.change_frame_with_type(1, Type::I32)?;
1683 }
1684 Operator::TableSize { table } => {
1685 self.check_reference_types_enabled()?;
1686 if table as usize >= resources.tables().len() {
1687 return Err("table index out of bounds");
1688 }
1689 self.func_state.change_frame_with_type(1, Type::I32)?;
1690 }
1691 }
1692 Ok(FunctionEnd::No)
1693 }
1694
process_end_function(&self) -> OperatorValidatorResult<()>1695 pub(crate) fn process_end_function(&self) -> OperatorValidatorResult<()> {
1696 if !self.func_state.end_function {
1697 return Err("expected end of function");
1698 }
1699 Ok(())
1700 }
1701 }
1702