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