1use crate::{
2 context::ModuleContext,
3 stack::StackWithLimit,
4 util::Locals,
5 Error,
6 FuncValidator,
7 DEFAULT_MEMORY_INDEX,
8 DEFAULT_TABLE_INDEX,
9};
10
11use core::u32;
12use parity_wasm::elements::{BlockType, Func, FuncBody, Instruction, TableElementType, ValueType};
13
14const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
16const DEFAULT_FRAME_STACK_LIMIT: usize = 16384;
18
19#[derive(Debug, Clone)]
21pub struct BlockFrame {
22 pub started_with: StartedWith,
24 pub block_type: BlockType,
27 pub value_stack_len: usize,
30 pub polymorphic_stack: bool,
34}
35
36#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40pub enum StartedWith {
41 Block,
42 If,
43 Else,
44 Loop,
45}
46
47#[derive(Debug, Clone, Copy)]
49pub enum StackValueType {
50 Any,
52 Specific(ValueType),
54}
55
56impl From<ValueType> for StackValueType {
57 fn from(value_type: ValueType) -> Self {
58 StackValueType::Specific(value_type)
59 }
60}
61
62impl PartialEq<StackValueType> for StackValueType {
63 fn eq(&self, other: &StackValueType) -> bool {
64 match (*self, *other) {
65 (StackValueType::Any, _) => true,
67 (_, StackValueType::Any) => true,
68 (StackValueType::Specific(self_ty), StackValueType::Specific(other_ty)) => {
69 self_ty == other_ty
70 }
71 }
72 }
73}
74
75impl PartialEq<ValueType> for StackValueType {
76 fn eq(&self, other: &ValueType) -> bool {
77 match *self {
78 StackValueType::Any => true,
79 StackValueType::Specific(value_ty) => value_ty == *other,
80 }
81 }
82}
83
84impl PartialEq<StackValueType> for ValueType {
85 fn eq(&self, other: &StackValueType) -> bool {
86 other == self
87 }
88}
89
90pub fn drive<T: FuncValidator>(
91 module: &ModuleContext,
92 func: &Func,
93 body: &FuncBody,
94 input: <T as FuncValidator>::Input,
95) -> Result<T::Output, Error> {
96 let (params, result_ty) = module.require_function_type(func.type_ref())?;
97
98 let code = body.code().elements();
99 let code_len = code.len();
100 if code_len == 0 {
101 return Err(Error("Non-empty function body expected".into()));
102 }
103
104 let mut context = FunctionValidationContext::new(
105 module,
106 Locals::new(params, body.locals())?,
107 DEFAULT_VALUE_STACK_LIMIT,
108 DEFAULT_FRAME_STACK_LIMIT,
109 result_ty,
110 )?;
111
112 let mut validator = T::new(&context, body, input);
113
114 for (position, instruction) in code.iter().enumerate() {
115 validator
116 .next_instruction(&mut context, instruction)
117 .map_err(|err| {
118 Error(format!(
119 "At instruction {:?}(@{}): {}",
120 instruction, position, err
121 ))
122 })?;
123 }
124
125 assert!(context.frame_stack.is_empty());
129
130 Ok(validator.finish(&context))
131}
132
133pub struct FunctionValidationContext<'a> {
135 pub module: &'a ModuleContext,
137 pub locals: Locals<'a>,
139 pub value_stack: StackWithLimit<StackValueType>,
141 pub frame_stack: StackWithLimit<BlockFrame>,
143 pub return_type: BlockType,
145}
146
147impl<'a> FunctionValidationContext<'a> {
148 fn new(
149 module: &'a ModuleContext,
150 locals: Locals<'a>,
151 value_stack_limit: usize,
152 frame_stack_limit: usize,
153 return_type: BlockType,
154 ) -> Result<Self, Error> {
155 let mut ctx = FunctionValidationContext {
156 module,
157 locals,
158 value_stack: StackWithLimit::with_limit(value_stack_limit),
159 frame_stack: StackWithLimit::with_limit(frame_stack_limit),
160 return_type,
161 };
162 push_label(
163 StartedWith::Block,
164 return_type,
165 &ctx.value_stack,
166 &mut ctx.frame_stack,
167 )?;
168 Ok(ctx)
169 }
170
171 pub fn step(&mut self, instruction: &Instruction) -> Result<(), Error> {
172 use self::Instruction::*;
173
174 match *instruction {
175 Nop => {}
177
178 Unreachable => {
179 make_top_frame_polymorphic(&mut self.value_stack, &mut self.frame_stack);
180 }
181
182 Block(block_type) => {
183 push_label(
184 StartedWith::Block,
185 block_type,
186 &self.value_stack,
187 &mut self.frame_stack,
188 )?;
189 }
190 Loop(block_type) => {
191 push_label(
192 StartedWith::Loop,
193 block_type,
194 &self.value_stack,
195 &mut self.frame_stack,
196 )?;
197 }
198 If(block_type) => {
199 pop_value(
200 &mut self.value_stack,
201 &self.frame_stack,
202 ValueType::I32.into(),
203 )?;
204 push_label(
205 StartedWith::If,
206 block_type,
207 &self.value_stack,
208 &mut self.frame_stack,
209 )?;
210 }
211 Else => {
212 let block_type = {
213 let top = top_label(&self.frame_stack);
214 if top.started_with != StartedWith::If {
215 return Err(Error("Misplaced else instruction".into()));
216 }
217 top.block_type
218 };
219
220 pop_label(&mut self.value_stack, &mut self.frame_stack)?;
223 push_label(
224 StartedWith::Else,
225 block_type,
226 &self.value_stack,
227 &mut self.frame_stack,
228 )?;
229 }
230 End => {
231 let block_type = {
232 let top = top_label(&self.frame_stack);
233
234 if top.started_with == StartedWith::If && top.block_type != BlockType::NoResult
235 {
236 return Err(Error(format!(
238 "If block without else required to have NoResult block type. But it has {:?} type",
239 top.block_type
240 )));
241 }
242
243 top.block_type
244 };
245
246 if self.frame_stack.len() == 1 {
248 if let BlockType::Value(value_type) = self.return_type {
252 tee_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
253 }
254
255 pop_label(&mut self.value_stack, &mut self.frame_stack)?;
256
257 } else {
261 pop_label(&mut self.value_stack, &mut self.frame_stack)?;
262
263 if let BlockType::Value(value_type) = block_type {
265 push_value(&mut self.value_stack, value_type.into())?;
266 }
267 }
268 }
269 Br(depth) => {
270 self.validate_br(depth)?;
271 make_top_frame_polymorphic(&mut self.value_stack, &mut self.frame_stack);
272 }
273 BrIf(depth) => {
274 self.validate_br_if(depth)?;
275 }
276 BrTable(ref br_table_data) => {
277 self.validate_br_table(&br_table_data.table, br_table_data.default)?;
278 make_top_frame_polymorphic(&mut self.value_stack, &mut self.frame_stack);
279 }
280 Return => {
281 if let BlockType::Value(value_type) = self.return_type {
282 tee_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
283 }
284 make_top_frame_polymorphic(&mut self.value_stack, &mut self.frame_stack);
285 }
286
287 Call(index) => {
288 self.validate_call(index)?;
289 }
290 CallIndirect(index, _reserved) => {
291 self.validate_call_indirect(index)?;
292 }
293
294 Drop => {
295 self.validate_drop()?;
296 }
297 Select => {
298 self.validate_select()?;
299 }
300
301 GetLocal(index) => {
302 self.validate_get_local(index)?;
303 }
304 SetLocal(index) => {
305 self.validate_set_local(index)?;
306 }
307 TeeLocal(index) => {
308 self.validate_tee_local(index)?;
309 }
310 GetGlobal(index) => {
311 self.validate_get_global(index)?;
312 }
313 SetGlobal(index) => {
314 self.validate_set_global(index)?;
315 }
316
317 I32Load(align, _) => {
318 self.validate_load(align, 4, ValueType::I32)?;
319 }
320 I64Load(align, _) => {
321 self.validate_load(align, 8, ValueType::I64)?;
322 }
323 F32Load(align, _) => {
324 self.validate_load(align, 4, ValueType::F32)?;
325 }
326 F64Load(align, _) => {
327 self.validate_load(align, 8, ValueType::F64)?;
328 }
329 I32Load8S(align, _) => {
330 self.validate_load(align, 1, ValueType::I32)?;
331 }
332 I32Load8U(align, _) => {
333 self.validate_load(align, 1, ValueType::I32)?;
334 }
335 I32Load16S(align, _) => {
336 self.validate_load(align, 2, ValueType::I32)?;
337 }
338 I32Load16U(align, _) => {
339 self.validate_load(align, 2, ValueType::I32)?;
340 }
341 I64Load8S(align, _) => {
342 self.validate_load(align, 1, ValueType::I64)?;
343 }
344 I64Load8U(align, _) => {
345 self.validate_load(align, 1, ValueType::I64)?;
346 }
347 I64Load16S(align, _) => {
348 self.validate_load(align, 2, ValueType::I64)?;
349 }
350 I64Load16U(align, _) => {
351 self.validate_load(align, 2, ValueType::I64)?;
352 }
353 I64Load32S(align, _) => {
354 self.validate_load(align, 4, ValueType::I64)?;
355 }
356 I64Load32U(align, _) => {
357 self.validate_load(align, 4, ValueType::I64)?;
358 }
359
360 I32Store(align, _) => {
361 self.validate_store(align, 4, ValueType::I32)?;
362 }
363 I64Store(align, _) => {
364 self.validate_store(align, 8, ValueType::I64)?;
365 }
366 F32Store(align, _) => {
367 self.validate_store(align, 4, ValueType::F32)?;
368 }
369 F64Store(align, _) => {
370 self.validate_store(align, 8, ValueType::F64)?;
371 }
372 I32Store8(align, _) => {
373 self.validate_store(align, 1, ValueType::I32)?;
374 }
375 I32Store16(align, _) => {
376 self.validate_store(align, 2, ValueType::I32)?;
377 }
378 I64Store8(align, _) => {
379 self.validate_store(align, 1, ValueType::I64)?;
380 }
381 I64Store16(align, _) => {
382 self.validate_store(align, 2, ValueType::I64)?;
383 }
384 I64Store32(align, _) => {
385 self.validate_store(align, 4, ValueType::I64)?;
386 }
387
388 CurrentMemory(_) => {
389 self.validate_current_memory()?;
390 }
391 GrowMemory(_) => {
392 self.validate_grow_memory()?;
393 }
394
395 I32Const(_) => {
396 self.validate_const(ValueType::I32)?;
397 }
398 I64Const(_) => {
399 self.validate_const(ValueType::I64)?;
400 }
401 F32Const(_) => {
402 self.validate_const(ValueType::F32)?;
403 }
404 F64Const(_) => {
405 self.validate_const(ValueType::F64)?;
406 }
407
408 I32Eqz => {
409 self.validate_testop(ValueType::I32)?;
410 }
411 I32Eq => {
412 self.validate_relop(ValueType::I32)?;
413 }
414 I32Ne => {
415 self.validate_relop(ValueType::I32)?;
416 }
417 I32LtS => {
418 self.validate_relop(ValueType::I32)?;
419 }
420 I32LtU => {
421 self.validate_relop(ValueType::I32)?;
422 }
423 I32GtS => {
424 self.validate_relop(ValueType::I32)?;
425 }
426 I32GtU => {
427 self.validate_relop(ValueType::I32)?;
428 }
429 I32LeS => {
430 self.validate_relop(ValueType::I32)?;
431 }
432 I32LeU => {
433 self.validate_relop(ValueType::I32)?;
434 }
435 I32GeS => {
436 self.validate_relop(ValueType::I32)?;
437 }
438 I32GeU => {
439 self.validate_relop(ValueType::I32)?;
440 }
441
442 I64Eqz => {
443 self.validate_testop(ValueType::I64)?;
444 }
445 I64Eq => {
446 self.validate_relop(ValueType::I64)?;
447 }
448 I64Ne => {
449 self.validate_relop(ValueType::I64)?;
450 }
451 I64LtS => {
452 self.validate_relop(ValueType::I64)?;
453 }
454 I64LtU => {
455 self.validate_relop(ValueType::I64)?;
456 }
457 I64GtS => {
458 self.validate_relop(ValueType::I64)?;
459 }
460 I64GtU => {
461 self.validate_relop(ValueType::I64)?;
462 }
463 I64LeS => {
464 self.validate_relop(ValueType::I64)?;
465 }
466 I64LeU => {
467 self.validate_relop(ValueType::I64)?;
468 }
469 I64GeS => {
470 self.validate_relop(ValueType::I64)?;
471 }
472 I64GeU => {
473 self.validate_relop(ValueType::I64)?;
474 }
475
476 F32Eq => {
477 self.validate_relop(ValueType::F32)?;
478 }
479 F32Ne => {
480 self.validate_relop(ValueType::F32)?;
481 }
482 F32Lt => {
483 self.validate_relop(ValueType::F32)?;
484 }
485 F32Gt => {
486 self.validate_relop(ValueType::F32)?;
487 }
488 F32Le => {
489 self.validate_relop(ValueType::F32)?;
490 }
491 F32Ge => {
492 self.validate_relop(ValueType::F32)?;
493 }
494
495 F64Eq => {
496 self.validate_relop(ValueType::F64)?;
497 }
498 F64Ne => {
499 self.validate_relop(ValueType::F64)?;
500 }
501 F64Lt => {
502 self.validate_relop(ValueType::F64)?;
503 }
504 F64Gt => {
505 self.validate_relop(ValueType::F64)?;
506 }
507 F64Le => {
508 self.validate_relop(ValueType::F64)?;
509 }
510 F64Ge => {
511 self.validate_relop(ValueType::F64)?;
512 }
513
514 I32Clz => {
515 self.validate_unop(ValueType::I32)?;
516 }
517 I32Ctz => {
518 self.validate_unop(ValueType::I32)?;
519 }
520 I32Popcnt => {
521 self.validate_unop(ValueType::I32)?;
522 }
523 I32Add => {
524 self.validate_binop(ValueType::I32)?;
525 }
526 I32Sub => {
527 self.validate_binop(ValueType::I32)?;
528 }
529 I32Mul => {
530 self.validate_binop(ValueType::I32)?;
531 }
532 I32DivS => {
533 self.validate_binop(ValueType::I32)?;
534 }
535 I32DivU => {
536 self.validate_binop(ValueType::I32)?;
537 }
538 I32RemS => {
539 self.validate_binop(ValueType::I32)?;
540 }
541 I32RemU => {
542 self.validate_binop(ValueType::I32)?;
543 }
544 I32And => {
545 self.validate_binop(ValueType::I32)?;
546 }
547 I32Or => {
548 self.validate_binop(ValueType::I32)?;
549 }
550 I32Xor => {
551 self.validate_binop(ValueType::I32)?;
552 }
553 I32Shl => {
554 self.validate_binop(ValueType::I32)?;
555 }
556 I32ShrS => {
557 self.validate_binop(ValueType::I32)?;
558 }
559 I32ShrU => {
560 self.validate_binop(ValueType::I32)?;
561 }
562 I32Rotl => {
563 self.validate_binop(ValueType::I32)?;
564 }
565 I32Rotr => {
566 self.validate_binop(ValueType::I32)?;
567 }
568
569 I64Clz => {
570 self.validate_unop(ValueType::I64)?;
571 }
572 I64Ctz => {
573 self.validate_unop(ValueType::I64)?;
574 }
575 I64Popcnt => {
576 self.validate_unop(ValueType::I64)?;
577 }
578 I64Add => {
579 self.validate_binop(ValueType::I64)?;
580 }
581 I64Sub => {
582 self.validate_binop(ValueType::I64)?;
583 }
584 I64Mul => {
585 self.validate_binop(ValueType::I64)?;
586 }
587 I64DivS => {
588 self.validate_binop(ValueType::I64)?;
589 }
590 I64DivU => {
591 self.validate_binop(ValueType::I64)?;
592 }
593 I64RemS => {
594 self.validate_binop(ValueType::I64)?;
595 }
596 I64RemU => {
597 self.validate_binop(ValueType::I64)?;
598 }
599 I64And => {
600 self.validate_binop(ValueType::I64)?;
601 }
602 I64Or => {
603 self.validate_binop(ValueType::I64)?;
604 }
605 I64Xor => {
606 self.validate_binop(ValueType::I64)?;
607 }
608 I64Shl => {
609 self.validate_binop(ValueType::I64)?;
610 }
611 I64ShrS => {
612 self.validate_binop(ValueType::I64)?;
613 }
614 I64ShrU => {
615 self.validate_binop(ValueType::I64)?;
616 }
617 I64Rotl => {
618 self.validate_binop(ValueType::I64)?;
619 }
620 I64Rotr => {
621 self.validate_binop(ValueType::I64)?;
622 }
623
624 F32Abs => {
625 self.validate_unop(ValueType::F32)?;
626 }
627 F32Neg => {
628 self.validate_unop(ValueType::F32)?;
629 }
630 F32Ceil => {
631 self.validate_unop(ValueType::F32)?;
632 }
633 F32Floor => {
634 self.validate_unop(ValueType::F32)?;
635 }
636 F32Trunc => {
637 self.validate_unop(ValueType::F32)?;
638 }
639 F32Nearest => {
640 self.validate_unop(ValueType::F32)?;
641 }
642 F32Sqrt => {
643 self.validate_unop(ValueType::F32)?;
644 }
645 F32Add => {
646 self.validate_binop(ValueType::F32)?;
647 }
648 F32Sub => {
649 self.validate_binop(ValueType::F32)?;
650 }
651 F32Mul => {
652 self.validate_binop(ValueType::F32)?;
653 }
654 F32Div => {
655 self.validate_binop(ValueType::F32)?;
656 }
657 F32Min => {
658 self.validate_binop(ValueType::F32)?;
659 }
660 F32Max => {
661 self.validate_binop(ValueType::F32)?;
662 }
663 F32Copysign => {
664 self.validate_binop(ValueType::F32)?;
665 }
666
667 F64Abs => {
668 self.validate_unop(ValueType::F64)?;
669 }
670 F64Neg => {
671 self.validate_unop(ValueType::F64)?;
672 }
673 F64Ceil => {
674 self.validate_unop(ValueType::F64)?;
675 }
676 F64Floor => {
677 self.validate_unop(ValueType::F64)?;
678 }
679 F64Trunc => {
680 self.validate_unop(ValueType::F64)?;
681 }
682 F64Nearest => {
683 self.validate_unop(ValueType::F64)?;
684 }
685 F64Sqrt => {
686 self.validate_unop(ValueType::F64)?;
687 }
688 F64Add => {
689 self.validate_binop(ValueType::F64)?;
690 }
691 F64Sub => {
692 self.validate_binop(ValueType::F64)?;
693 }
694 F64Mul => {
695 self.validate_binop(ValueType::F64)?;
696 }
697 F64Div => {
698 self.validate_binop(ValueType::F64)?;
699 }
700 F64Min => {
701 self.validate_binop(ValueType::F64)?;
702 }
703 F64Max => {
704 self.validate_binop(ValueType::F64)?;
705 }
706 F64Copysign => {
707 self.validate_binop(ValueType::F64)?;
708 }
709
710 I32WrapI64 => {
711 self.validate_cvtop(ValueType::I64, ValueType::I32)?;
712 }
713 I32TruncSF32 => {
714 self.validate_cvtop(ValueType::F32, ValueType::I32)?;
715 }
716 I32TruncUF32 => {
717 self.validate_cvtop(ValueType::F32, ValueType::I32)?;
718 }
719 I32TruncSF64 => {
720 self.validate_cvtop(ValueType::F64, ValueType::I32)?;
721 }
722 I32TruncUF64 => {
723 self.validate_cvtop(ValueType::F64, ValueType::I32)?;
724 }
725 I64ExtendSI32 => {
726 self.validate_cvtop(ValueType::I32, ValueType::I64)?;
727 }
728 I64ExtendUI32 => {
729 self.validate_cvtop(ValueType::I32, ValueType::I64)?;
730 }
731 I64TruncSF32 => {
732 self.validate_cvtop(ValueType::F32, ValueType::I64)?;
733 }
734 I64TruncUF32 => {
735 self.validate_cvtop(ValueType::F32, ValueType::I64)?;
736 }
737 I64TruncSF64 => {
738 self.validate_cvtop(ValueType::F64, ValueType::I64)?;
739 }
740 I64TruncUF64 => {
741 self.validate_cvtop(ValueType::F64, ValueType::I64)?;
742 }
743 F32ConvertSI32 => {
744 self.validate_cvtop(ValueType::I32, ValueType::F32)?;
745 }
746 F32ConvertUI32 => {
747 self.validate_cvtop(ValueType::I32, ValueType::F32)?;
748 }
749 F32ConvertSI64 => {
750 self.validate_cvtop(ValueType::I64, ValueType::F32)?;
751 }
752 F32ConvertUI64 => {
753 self.validate_cvtop(ValueType::I64, ValueType::F32)?;
754 }
755 F32DemoteF64 => {
756 self.validate_cvtop(ValueType::F64, ValueType::F32)?;
757 }
758 F64ConvertSI32 => {
759 self.validate_cvtop(ValueType::I32, ValueType::F64)?;
760 }
761 F64ConvertUI32 => {
762 self.validate_cvtop(ValueType::I32, ValueType::F64)?;
763 }
764 F64ConvertSI64 => {
765 self.validate_cvtop(ValueType::I64, ValueType::F64)?;
766 }
767 F64ConvertUI64 => {
768 self.validate_cvtop(ValueType::I64, ValueType::F64)?;
769 }
770 F64PromoteF32 => {
771 self.validate_cvtop(ValueType::F32, ValueType::F64)?;
772 }
773
774 I32ReinterpretF32 => {
775 self.validate_cvtop(ValueType::F32, ValueType::I32)?;
776 }
777 I64ReinterpretF64 => {
778 self.validate_cvtop(ValueType::F64, ValueType::I64)?;
779 }
780 F32ReinterpretI32 => {
781 self.validate_cvtop(ValueType::I32, ValueType::F32)?;
782 }
783 F64ReinterpretI64 => {
784 self.validate_cvtop(ValueType::I64, ValueType::F64)?;
785 }
786 }
787
788 Ok(())
789 }
790
791 fn validate_const(&mut self, value_type: ValueType) -> Result<(), Error> {
792 push_value(&mut self.value_stack, value_type.into())?;
793 Ok(())
794 }
795
796 fn validate_unop(&mut self, value_type: ValueType) -> Result<(), Error> {
797 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
798 push_value(&mut self.value_stack, value_type.into())?;
799 Ok(())
800 }
801
802 fn validate_binop(&mut self, value_type: ValueType) -> Result<(), Error> {
803 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
804 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
805 push_value(&mut self.value_stack, value_type.into())?;
806 Ok(())
807 }
808
809 fn validate_testop(&mut self, value_type: ValueType) -> Result<(), Error> {
810 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
811 push_value(&mut self.value_stack, ValueType::I32.into())?;
812 Ok(())
813 }
814
815 fn validate_relop(&mut self, value_type: ValueType) -> Result<(), Error> {
816 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
817 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
818 push_value(&mut self.value_stack, ValueType::I32.into())?;
819 Ok(())
820 }
821
822 fn validate_cvtop(
823 &mut self,
824 value_type1: ValueType,
825 value_type2: ValueType,
826 ) -> Result<(), Error> {
827 pop_value(&mut self.value_stack, &self.frame_stack, value_type1.into())?;
828 push_value(&mut self.value_stack, value_type2.into())?;
829 Ok(())
830 }
831
832 fn validate_drop(&mut self) -> Result<(), Error> {
833 pop_value(
834 &mut self.value_stack,
835 &self.frame_stack,
836 StackValueType::Any,
837 )?;
838 Ok(())
839 }
840
841 fn validate_select(&mut self) -> Result<(), Error> {
842 pop_value(
843 &mut self.value_stack,
844 &self.frame_stack,
845 ValueType::I32.into(),
846 )?;
847 let select_type = pop_value(
848 &mut self.value_stack,
849 &self.frame_stack,
850 StackValueType::Any,
851 )?;
852 pop_value(&mut self.value_stack, &self.frame_stack, select_type)?;
853 push_value(&mut self.value_stack, select_type)?;
854 Ok(())
855 }
856
857 fn validate_get_local(&mut self, index: u32) -> Result<(), Error> {
858 let local_type = require_local(&self.locals, index)?;
859 push_value(&mut self.value_stack, local_type.into())?;
860 Ok(())
861 }
862
863 fn validate_set_local(&mut self, index: u32) -> Result<(), Error> {
864 let local_type = require_local(&self.locals, index)?;
865 let value_type = pop_value(
866 &mut self.value_stack,
867 &self.frame_stack,
868 StackValueType::Any,
869 )?;
870 if local_type != value_type {
871 return Err(Error(format!(
872 "Trying to update local {} of type {:?} with value of type {:?}",
873 index, local_type, value_type
874 )));
875 }
876 Ok(())
877 }
878
879 fn validate_tee_local(&mut self, index: u32) -> Result<(), Error> {
880 let local_type = require_local(&self.locals, index)?;
881 tee_value(&mut self.value_stack, &self.frame_stack, local_type.into())?;
882 Ok(())
883 }
884
885 fn validate_get_global(&mut self, index: u32) -> Result<(), Error> {
886 let global_type: StackValueType = {
887 let global = self.module.require_global(index, None)?;
888 global.content_type().into()
889 };
890 push_value(&mut self.value_stack, global_type)?;
891 Ok(())
892 }
893
894 fn validate_set_global(&mut self, index: u32) -> Result<(), Error> {
895 let global_type: StackValueType = {
896 let global = self.module.require_global(index, Some(true))?;
897 global.content_type().into()
898 };
899 let value_type = pop_value(
900 &mut self.value_stack,
901 &self.frame_stack,
902 StackValueType::Any,
903 )?;
904 if global_type != value_type {
905 return Err(Error(format!(
906 "Trying to update global {} of type {:?} with value of type {:?}",
907 index, global_type, value_type
908 )));
909 }
910 Ok(())
911 }
912
913 fn validate_load(
914 &mut self,
915 align: u32,
916 max_align: u32,
917 value_type: ValueType,
918 ) -> Result<(), Error> {
919 if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align {
920 return Err(Error(format!(
921 "Too large memory alignment 2^{} (expected at most {})",
922 align, max_align
923 )));
924 }
925
926 pop_value(
927 &mut self.value_stack,
928 &self.frame_stack,
929 ValueType::I32.into(),
930 )?;
931 self.module.require_memory(DEFAULT_MEMORY_INDEX)?;
932 push_value(&mut self.value_stack, value_type.into())?;
933 Ok(())
934 }
935
936 fn validate_store(
937 &mut self,
938 align: u32,
939 max_align: u32,
940 value_type: ValueType,
941 ) -> Result<(), Error> {
942 if 1u32.checked_shl(align).unwrap_or(u32::MAX) > max_align {
943 return Err(Error(format!(
944 "Too large memory alignment 2^{} (expected at most {})",
945 align, max_align
946 )));
947 }
948
949 self.module.require_memory(DEFAULT_MEMORY_INDEX)?;
950 pop_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
951 pop_value(
952 &mut self.value_stack,
953 &self.frame_stack,
954 ValueType::I32.into(),
955 )?;
956 Ok(())
957 }
958
959 fn validate_br(&mut self, depth: u32) -> Result<(), Error> {
960 let (started_with, frame_block_type) = {
961 let frame = require_label(depth, &self.frame_stack)?;
962 (frame.started_with, frame.block_type)
963 };
964 if started_with != StartedWith::Loop {
965 if let BlockType::Value(value_type) = frame_block_type {
966 tee_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
967 }
968 }
969 Ok(())
970 }
971
972 fn validate_br_if(&mut self, depth: u32) -> Result<(), Error> {
973 pop_value(
974 &mut self.value_stack,
975 &self.frame_stack,
976 ValueType::I32.into(),
977 )?;
978
979 let (started_with, frame_block_type) = {
980 let frame = require_label(depth, &self.frame_stack)?;
981 (frame.started_with, frame.block_type)
982 };
983 if started_with != StartedWith::Loop {
984 if let BlockType::Value(value_type) = frame_block_type {
985 tee_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
986 }
987 }
988 Ok(())
989 }
990
991 fn validate_br_table(&mut self, table: &[u32], default: u32) -> Result<(), Error> {
992 let required_block_type: BlockType = {
993 let default_block = require_label(default, &self.frame_stack)?;
994 let required_block_type = if default_block.started_with == StartedWith::Loop {
995 BlockType::NoResult
996 } else {
997 default_block.block_type
998 };
999
1000 for label in table {
1001 let label_block = require_label(*label, &self.frame_stack)?;
1002 let label_block_type = if label_block.started_with == StartedWith::Loop {
1003 BlockType::NoResult
1004 } else {
1005 label_block.block_type
1006 };
1007 if required_block_type != label_block_type {
1008 return Err(Error(format!(
1009 "Labels in br_table points to block of different types: {:?} and {:?}",
1010 required_block_type, label_block.block_type
1011 )));
1012 }
1013 }
1014 required_block_type
1015 };
1016
1017 pop_value(
1018 &mut self.value_stack,
1019 &self.frame_stack,
1020 ValueType::I32.into(),
1021 )?;
1022 if let BlockType::Value(value_type) = required_block_type {
1023 tee_value(&mut self.value_stack, &self.frame_stack, value_type.into())?;
1024 }
1025
1026 Ok(())
1027 }
1028
1029 fn validate_call(&mut self, idx: u32) -> Result<(), Error> {
1030 let (argument_types, return_type) = self.module.require_function(idx)?;
1031 for argument_type in argument_types.iter().rev() {
1032 pop_value(
1033 &mut self.value_stack,
1034 &self.frame_stack,
1035 (*argument_type).into(),
1036 )?;
1037 }
1038 if let BlockType::Value(value_type) = return_type {
1039 push_value(&mut self.value_stack, value_type.into())?;
1040 }
1041 Ok(())
1042 }
1043
1044 fn validate_call_indirect(&mut self, idx: u32) -> Result<(), Error> {
1045 {
1046 let table = self.module.require_table(DEFAULT_TABLE_INDEX)?;
1047 if table.elem_type() != TableElementType::AnyFunc {
1048 return Err(Error(format!(
1049 "Table {} has element type {:?} while `anyfunc` expected",
1050 idx,
1051 table.elem_type()
1052 )));
1053 }
1054 }
1055
1056 pop_value(
1057 &mut self.value_stack,
1058 &self.frame_stack,
1059 ValueType::I32.into(),
1060 )?;
1061 let (argument_types, return_type) = self.module.require_function_type(idx)?;
1062 for argument_type in argument_types.iter().rev() {
1063 pop_value(
1064 &mut self.value_stack,
1065 &self.frame_stack,
1066 (*argument_type).into(),
1067 )?;
1068 }
1069 if let BlockType::Value(value_type) = return_type {
1070 push_value(&mut self.value_stack, value_type.into())?;
1071 }
1072 Ok(())
1073 }
1074
1075 fn validate_current_memory(&mut self) -> Result<(), Error> {
1076 self.module.require_memory(DEFAULT_MEMORY_INDEX)?;
1077 push_value(&mut self.value_stack, ValueType::I32.into())?;
1078 Ok(())
1079 }
1080
1081 fn validate_grow_memory(&mut self) -> Result<(), Error> {
1082 self.module.require_memory(DEFAULT_MEMORY_INDEX)?;
1083 pop_value(
1084 &mut self.value_stack,
1085 &self.frame_stack,
1086 ValueType::I32.into(),
1087 )?;
1088 push_value(&mut self.value_stack, ValueType::I32.into())?;
1089 Ok(())
1090 }
1091}
1092
1093fn make_top_frame_polymorphic(
1094 value_stack: &mut StackWithLimit<StackValueType>,
1095 frame_stack: &mut StackWithLimit<BlockFrame>,
1096) {
1097 let frame = frame_stack
1098 .top_mut()
1099 .expect("make_top_frame_polymorphic is called with empty frame stack");
1100 value_stack.resize(frame.value_stack_len, StackValueType::Any);
1101 frame.polymorphic_stack = true;
1102}
1103
1104fn push_value(
1105 value_stack: &mut StackWithLimit<StackValueType>,
1106 value_type: StackValueType,
1107) -> Result<(), Error> {
1108 Ok(value_stack.push(value_type)?)
1109}
1110
1111fn pop_value(
1112 value_stack: &mut StackWithLimit<StackValueType>,
1113 frame_stack: &StackWithLimit<BlockFrame>,
1114 expected_value_ty: StackValueType,
1115) -> Result<StackValueType, Error> {
1116 let (is_stack_polymorphic, label_value_stack_len) = {
1117 let frame = top_label(frame_stack);
1118 (frame.polymorphic_stack, frame.value_stack_len)
1119 };
1120 let stack_is_empty = value_stack.len() == label_value_stack_len;
1121 let actual_value = if stack_is_empty && is_stack_polymorphic {
1122 StackValueType::Any
1123 } else {
1124 let value_stack_min = frame_stack
1125 .top()
1126 .expect("at least 1 topmost block")
1127 .value_stack_len;
1128 if value_stack.len() <= value_stack_min {
1129 return Err(Error("Trying to access parent frame stack values.".into()));
1130 }
1131 value_stack.pop()?
1132 };
1133 match actual_value {
1134 StackValueType::Specific(stack_value_type) if stack_value_type == expected_value_ty => {
1135 Ok(actual_value)
1136 }
1137 StackValueType::Any => Ok(actual_value),
1138 stack_value_type => Err(Error(format!(
1139 "Expected value of type {:?} on top of stack. Got {:?}",
1140 expected_value_ty, stack_value_type
1141 ))),
1142 }
1143}
1144
1145fn tee_value(
1146 value_stack: &mut StackWithLimit<StackValueType>,
1147 frame_stack: &StackWithLimit<BlockFrame>,
1148 value_type: StackValueType,
1149) -> Result<(), Error> {
1150 let _ = pop_value(value_stack, frame_stack, value_type)?;
1151 push_value(value_stack, value_type)?;
1152 Ok(())
1153}
1154
1155fn push_label(
1156 started_with: StartedWith,
1157 block_type: BlockType,
1158 value_stack: &StackWithLimit<StackValueType>,
1159 frame_stack: &mut StackWithLimit<BlockFrame>,
1160) -> Result<(), Error> {
1161 Ok(frame_stack.push(BlockFrame {
1162 started_with,
1163 block_type,
1164 value_stack_len: value_stack.len(),
1165 polymorphic_stack: false,
1166 })?)
1167}
1168
1169fn pop_label(
1171 value_stack: &mut StackWithLimit<StackValueType>,
1172 frame_stack: &mut StackWithLimit<BlockFrame>,
1173) -> Result<(), Error> {
1174 let block_type = frame_stack.top()?.block_type;
1178 match block_type {
1179 BlockType::NoResult => (),
1180 BlockType::Value(required_value_type) => {
1181 let _ = pop_value(
1182 value_stack,
1183 frame_stack,
1184 StackValueType::Specific(required_value_type),
1185 )?;
1186 }
1187 }
1188
1189 let frame = frame_stack.pop()?;
1190 if value_stack.len() != frame.value_stack_len {
1191 return Err(Error(format!(
1192 "Unexpected stack height {}, expected {}",
1193 value_stack.len(),
1194 frame.value_stack_len
1195 )));
1196 }
1197
1198 Ok(())
1199}
1200
1201pub fn top_label(frame_stack: &StackWithLimit<BlockFrame>) -> &BlockFrame {
1209 frame_stack
1210 .top()
1211 .expect("this function can't be called with empty frame stack")
1212}
1213
1214pub fn require_label(
1215 depth: u32,
1216 frame_stack: &StackWithLimit<BlockFrame>,
1217) -> Result<&BlockFrame, Error> {
1218 Ok(frame_stack.get(depth as usize)?)
1219}
1220
1221fn require_local(locals: &Locals, idx: u32) -> Result<ValueType, Error> {
1222 locals.type_of_local(idx)
1223}