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