Skip to content

Commit

Permalink
Add empty ValidMode and Prepare (#725)
Browse files Browse the repository at this point in the history
The next step is to add `Verify` with optimizations.

#46

---------

Co-authored-by: Zhou Fang <[email protected]>
Co-authored-by: Julien Cretin <[email protected]>
  • Loading branch information
3 people authored Jan 22, 2025
1 parent 8017774 commit 551e9db
Showing 1 changed file with 32 additions and 19 deletions.
51 changes: 32 additions & 19 deletions crates/interpreter/src/valid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use alloc::collections::BTreeSet;
use alloc::vec;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::marker::PhantomData;
use core::ops::Range;

use crate::error::*;
Expand All @@ -27,24 +28,32 @@ use crate::*;

/// Checks whether a WASM module in binary format is valid.
pub fn validate(binary: &[u8]) -> Result<Vec<MetadataEntry>, Error> {
Context::default().check_module(&mut Parser::new(binary))
Context::<Prepare>::default().check_module(&mut Parser::new(binary))
}

pub trait ValidMode: Default {}

#[derive(Default)]
pub struct Prepare;
impl ValidMode for Prepare {}

type Parser<'m> = parser::Parser<'m, Check>;
type CheckResult = MResult<(), Check>;

#[derive(Default)]
struct Context<'m> {
struct Context<'m, M: ValidMode> {
types: Vec<FuncType<'m>>,
funcs: Vec<TypeIdx>,
tables: Vec<TableType>,
mems: Vec<MemType>,
globals: Vec<GlobalType>,
elems: Vec<RefType>,
datas: Option<usize>,
#[allow(dead_code)]
mode: PhantomData<M>,
}

impl<'m> Context<'m> {
impl<'m, M: ValidMode> Context<'m, M> {
fn check_module(&mut self, parser: &mut Parser<'m>) -> MResult<Vec<MetadataEntry>, Check> {
check(parser.parse_bytes(8)? == b"\0asm\x01\0\0\0")?;
let module_start = parser.save().as_ptr() as usize;
Expand Down Expand Up @@ -263,16 +272,18 @@ impl<'m> Context<'m> {
}
}

struct ParseElem<'a, 'm> {
context: &'a mut Context<'m>,
struct ParseElem<'a, 'm, M: ValidMode> {
context: &'a mut Context<'m, M>,
refs: &'a mut [bool],
num_global_imports: usize,
table_type: OpdType,
elem_type: RefType,
}

impl<'a, 'm> ParseElem<'a, 'm> {
fn new(context: &'a mut Context<'m>, refs: &'a mut [bool], num_global_imports: usize) -> Self {
impl<'a, 'm, M: ValidMode> ParseElem<'a, 'm, M> {
fn new(
context: &'a mut Context<'m, M>, refs: &'a mut [bool], num_global_imports: usize,
) -> Self {
Self {
context,
num_global_imports,
Expand All @@ -283,7 +294,7 @@ impl<'a, 'm> ParseElem<'a, 'm> {
}
}

impl<'m> parser::ParseElem<'m, Check> for ParseElem<'_, 'm> {
impl<'m, M: ValidMode> parser::ParseElem<'m, Check> for ParseElem<'_, 'm, M> {
fn mode(&mut self, mode: parser::ElemMode<'_, 'm, Check>) -> MResult<(), Check> {
if let parser::ElemMode::Active { table, offset } = mode {
Expr::check_const(
Expand Down Expand Up @@ -322,19 +333,21 @@ impl<'m> parser::ParseElem<'m, Check> for ParseElem<'_, 'm> {
}
}

struct ParseData<'a, 'm> {
context: &'a mut Context<'m>,
struct ParseData<'a, 'm, M: ValidMode> {
context: &'a mut Context<'m, M>,
refs: &'a mut [bool],
num_global_imports: usize,
}

impl<'a, 'm> ParseData<'a, 'm> {
fn new(context: &'a mut Context<'m>, refs: &'a mut [bool], num_global_imports: usize) -> Self {
impl<'a, 'm, M: ValidMode> ParseData<'a, 'm, M> {
fn new(
context: &'a mut Context<'m, M>, refs: &'a mut [bool], num_global_imports: usize,
) -> Self {
Self { context, refs, num_global_imports }
}
}

impl<'m> parser::ParseData<'m, Check> for ParseData<'_, 'm> {
impl<'m, M: ValidMode> parser::ParseData<'m, Check> for ParseData<'_, 'm, M> {
fn mode(&mut self, mode: parser::DataMode<'_, 'm, Check>) -> MResult<(), Check> {
if let parser::DataMode::Active { memory, offset } = mode {
self.context.mem(memory)?;
Expand Down Expand Up @@ -406,8 +419,8 @@ impl OpdType {
}
}

struct Expr<'a, 'm> {
context: &'a Context<'m>,
struct Expr<'a, 'm, M: ValidMode> {
context: &'a Context<'m, M>,
parser: &'a mut Parser<'m>,
globals_len: usize,
/// Whether the expression is const and the function references.
Expand Down Expand Up @@ -515,9 +528,9 @@ enum LabelKind<'m> {
If(SideTableBranch<'m>),
}

impl<'a, 'm> Expr<'a, 'm> {
impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> {
fn new(
context: &'a Context<'m>, parser: &'a mut Parser<'m>,
context: &'a Context<'m, M>, parser: &'a mut Parser<'m>,
is_const: Result<&'a mut [bool], &'a [bool]>,
) -> Self {
Self {
Expand All @@ -533,7 +546,7 @@ impl<'a, 'm> Expr<'a, 'm> {
}

fn check_const(
context: &'a Context<'m>, parser: &'a mut Parser<'m>, refs: &'a mut [bool],
context: &'a Context<'m, M>, parser: &'a mut Parser<'m>, refs: &'a mut [bool],
num_global_imports: usize, expected: ResultType<'m>,
) -> CheckResult {
let mut expr = Expr::new(context, parser, Ok(refs));
Expand All @@ -543,7 +556,7 @@ impl<'a, 'm> Expr<'a, 'm> {
}

fn check_body(
context: &'a Context<'m>, parser: &'a mut Parser<'m>, refs: &'a [bool],
context: &'a Context<'m, M>, parser: &'a mut Parser<'m>, refs: &'a [bool],
locals: Vec<ValType>, results: ResultType<'m>,
) -> MResult<Vec<BranchTableEntry>, Check> {
let mut expr = Expr::new(context, parser, Err(refs));
Expand Down

0 comments on commit 551e9db

Please sign in to comment.