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