zingen/
validator.rs

1//! Pre-visitor for parsing WASM.
2
3use crate::{Function, Result};
4use wasmparser::{Operator, VisitOperator};
5
6/// A pre-visitor that validates the WASM and then visits it.
7pub struct ValidateThenVisit<'a, T>(pub T, pub &'a mut Function);
8
9macro_rules! validate_then_visit {
10    ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
11        $(
12            fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
13                self.0.$visit($($($arg.clone()),*)?)?;
14                // Only visit operators if the compiler is in a reachable code state. If
15                // the compiler is in an unreachable code state, most of the operators are
16                // ignored except for If, Block, Loop, Else and End. These operators need
17                // to be observed in order to keep the control stack frames balanced and to
18                // determine if reachability should be restored.
19                let visit_when_unreachable = visit_op_when_unreachable(Operator::$op $({ $($arg: $arg.clone()),* })?);
20                if true || visit_when_unreachable  {
21                    Ok(self.1.$visit($($($arg),*)?))
22                } else {
23                    Ok(Ok(()))
24                }
25            }
26        )*
27    };
28}
29
30fn visit_op_when_unreachable(op: Operator) -> bool {
31    use Operator::*;
32    matches!(op, If { .. } | Block { .. } | Loop { .. } | Else | End)
33}
34
35// /// Trait to handle reachability state.
36// trait ReachableState {
37//     /// Returns true if the current state of the program is reachable.
38//     fn is_reachable(&self) -> bool;
39// }
40//
41// impl ReachableState for Function {
42//     fn is_reachable(&self) -> bool {
43//         true
44//     }
45// }
46
47impl<'a, T> VisitOperator<'a> for ValidateThenVisit<'_, T>
48where
49    T: VisitOperator<'a, Output = wasmparser::Result<()>>,
50{
51    type Output = Result<Result<()>>;
52
53    wasmparser::for_each_operator!(validate_then_visit);
54}