wasmi_validation/
func.rs

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