xwasmi_validation/
func.rs

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