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