twasmi_validation/
func.rs

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
9/// Maximum number of entries in value stack per function.
10const DEFAULT_VALUE_STACK_LIMIT: usize = 16384;
11/// Maximum number of entries in frame stack per function.
12const DEFAULT_FRAME_STACK_LIMIT: usize = 16384;
13
14/// Control stack frame.
15#[derive(Debug, Clone)]
16pub struct BlockFrame {
17    /// The opcode that started this block frame.
18    pub started_with: StartedWith,
19    /// A signature, which is a block signature type indicating the number and types of result
20    /// values of the region.
21    pub block_type: BlockType,
22    /// A limit integer value, which is an index into the value stack indicating where to reset it
23    /// to on a branch to that label.
24    pub value_stack_len: usize,
25    /// Boolean which signals whether value stack became polymorphic. Value stack starts in
26    /// a non-polymorphic state and becomes polymorphic only after an instruction that never passes
27    /// control further is executed, i.e. `unreachable`, `br` (but not `br_if`!), etc.
28    pub polymorphic_stack: bool,
29}
30
31/// An opcode that opened the particular frame.
32///
33/// We need that to ensure proper combinations with `End` instruction.
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
35pub enum StartedWith {
36    Block,
37    If,
38    Else,
39    Loop,
40}
41
42/// Value type on the stack.
43#[derive(Debug, Clone, Copy)]
44pub enum StackValueType {
45    /// Any value type.
46    Any,
47    /// Concrete value type.
48    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            // Any type is equal with any other type.
61            (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    // The last `end` opcode should pop last instruction.
120    // tetsy-wasm ensures that there is always `End` opcode at
121    // the end of the function body.
122    assert!(context.frame_stack.is_empty());
123
124    Ok(validator.finish())
125}
126
127/// Function validation context.
128pub struct FunctionValidationContext<'a> {
129    /// Wasm module
130    pub module: &'a ModuleContext,
131    /// Local variables.
132    pub locals: Locals<'a>,
133    /// Value stack.
134    pub value_stack: StackWithLimit<StackValueType>,
135    /// Frame stack.
136    pub frame_stack: StackWithLimit<BlockFrame>,
137    /// Function return type.
138    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 instruction doesn't do anything. It is safe to just skip it.
170            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                // Then, we pop the current label. It discards all values that pushed in the current
215                // frame.
216                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                        // A `if` without an `else` can't return a result.
231                        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                    // We are about to close the last frame.
242
243                    // Check the return type.
244                    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                    // We just poped the last frame. To avoid some difficulties
251                    // we prefer to keep this branch explicit and bail out here.
252                    ()
253                } else {
254                    pop_label(&mut self.value_stack, &mut self.frame_stack)?;
255
256                    // Push the result value.
257                    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
1162// TODO: Refactor
1163fn pop_label(
1164    value_stack: &mut StackWithLimit<StackValueType>,
1165    frame_stack: &mut StackWithLimit<BlockFrame>,
1166) -> Result<(), Error> {
1167    // Don't pop frame yet. This is essential since we still might pop values from the value stack
1168    // and this in turn requires current frame to check whether or not we've reached
1169    // unreachable.
1170    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
1194/// Returns the top most frame from the frame stack.
1195///
1196/// # Panics
1197///
1198/// Can be called only when the frame stack is not empty: that is, it is ok to call this function
1199/// after initialization of the validation and until the validation reached the latest `End`
1200/// operator.
1201pub 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}