Skip to content

Commit

Permalink
feat: validate module opcodes, logging feature
Browse files Browse the repository at this point in the history
Signed-off-by: Henry Gressmann <[email protected]>
  • Loading branch information
explodingcamera committed Dec 6, 2023
1 parent ef4dbf2 commit 5f928b7
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 38 deletions.
146 changes: 146 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ path="src/bin.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tinywasm={path="../tinywasm"}
tinywasm={path="../tinywasm", features=["std", "parser"]}
argh="0.1"
color-eyre={version="0.6", default-features=false}
log="0.4"
Expand Down
6 changes: 5 additions & 1 deletion crates/cli/src/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,16 @@ fn main() -> Result<()> {

fn run(module: Module) -> Result<()> {
let mut store = tinywasm::Store::default();

let instance = module.instantiate(&mut store)?;

let func = instance.get_typed_func::<(i32, i32), (i32,)>(&store, "add")?;
let (res,) = func.call(&mut store, (2, 2))?;
info!("{res:?}");

// let func = instance.get_func(&store, "add")?;
// let params = vec![WasmValue::I32(2), WasmValue::I32(2)];
// let res = func.call(&mut store, &params)?;
// info!("{res:?}");

Ok(())
}
5 changes: 3 additions & 2 deletions crates/parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ edition="2021"
# fork of wasmparser with no_std support, see https://github.com/bytecodealliance/wasmtime/issues/3495
# TODO: create dependency free parser
wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}
log="0.4"
log={version="0.4", optional=true}
tinywasm-types={path="../types"}

[features]
default=["std"]
default=["std", "logging"]
logging=["log"]
std=[]
32 changes: 23 additions & 9 deletions crates/parser/src/conversion.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
use tinywasm_types::{BlockArgs, Export, ExternalKind, FuncType, Instruction, MemArg, ValType};
use wasmparser::{FuncValidator, ValidatorResources};

use crate::{module::CodeSection, Result};

Expand All @@ -24,23 +25,28 @@ pub(crate) fn convert_module_export(export: wasmparser::Export) -> Result<Export
})
}

pub(crate) fn convert_module_code(func: wasmparser::FunctionBody) -> Result<CodeSection> {
pub(crate) fn convert_module_code(
func: wasmparser::FunctionBody,
mut validator: FuncValidator<ValidatorResources>,
) -> Result<CodeSection> {
let locals_reader = func.get_locals_reader()?;
let count = locals_reader.get_count();
let mut locals = Vec::with_capacity(count as usize);
locals.extend(
locals_reader
.into_iter()
.filter_map(|l| l.ok())
.map(|l| convert_valtype(&l.1)),
);

for (i, local) in locals_reader.into_iter().enumerate() {
let local = local?;
for _ in 0..local.0 {
locals.push(convert_valtype(&local.1));
}
validator.define_locals(i, local.0, local.1)?;
}

if locals.len() != count as usize {
return Err(crate::ParseError::Other("Invalid local index".to_string()));
}

let body_reader = func.get_operators_reader()?;
let body = process_operators(body_reader.into_iter())?;
let body = process_operators(body_reader.into_iter(), validator)?;

Ok(CodeSection {
locals: locals.into_boxed_slice(),
Expand Down Expand Up @@ -106,12 +112,18 @@ pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemArg {

pub fn process_operators<'a>(
ops: impl Iterator<Item = Result<wasmparser::Operator<'a>, wasmparser::BinaryReaderError>>,
mut validator: FuncValidator<ValidatorResources>,
) -> Result<Box<[Instruction]>> {
let mut instructions = Vec::new();

let mut offset = 0;
for op in ops {
let op = op?;
validator.op(offset, &op)?;
offset += 1;

use wasmparser::Operator::*;
let res = match op? {
let res = match op {
BrTable { targets } => {
let def = targets.default();
let targets = targets
Expand Down Expand Up @@ -303,5 +315,7 @@ pub fn process_operators<'a>(
instructions.push(res);
}

validator.finish(offset)?;

Ok(instructions.into_boxed_slice())
}
11 changes: 11 additions & 0 deletions crates/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
mod std;
extern crate alloc;

// log for logging (optional).
#[cfg(feature = "logging")]
#[allow(clippy::single_component_path_imports)]
use log;

#[cfg(not(feature = "logging"))]
mod log {
macro_rules! debug ( ($($tt:tt)*) => {{}} );
pub(crate) use debug;
}

mod conversion;
mod error;
mod module;
Expand Down
8 changes: 5 additions & 3 deletions crates/parser/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::log::debug;
use alloc::{boxed::Box, format, vec::Vec};
use core::fmt::Debug;
use log::debug;
use tinywasm_types::{Export, FuncType, Instruction, ValType};
use wasmparser::{Payload, Validator};

Expand Down Expand Up @@ -124,9 +124,11 @@ impl ModuleReader {
}
CodeSectionEntry(function) => {
debug!("Found code section entry");
validator.code_section_entry(&function)?;
let v = validator.code_section_entry(&function)?;
let func_validator = v.into_validator(Default::default());

self.code_section.push(conversion::convert_module_code(function)?);
self.code_section
.push(conversion::convert_module_code(function, func_validator)?);
}
ImportSection(_reader) => {
return Err(ParseError::UnsupportedSection("Import section".into()));
Expand Down
11 changes: 6 additions & 5 deletions crates/tinywasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ path="src/lib.rs"
crate-type=["cdylib", "rlib"]

[dependencies]
log="0.4"
tinywasm-parser={path="../parser", default-features=false}
log={version="0.4", optional=true}
tinywasm-parser={path="../parser", default-features=false, optional=true}
tinywasm-types={path="../types", default-features=false}

wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}

[features]
default=["std"]
std=["tinywasm-parser/std", "tinywasm-types/std"]
default=["std", "parser", "logging"]
logging=["log", "tinywasm-types/logging", "tinywasm-parser?/logging"]
std=["tinywasm-parser?/std", "tinywasm-types/std"]
parser=["tinywasm-parser"]
Loading

0 comments on commit 5f928b7

Please sign in to comment.