Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): transactions for the wasm reader #69

Merged
merged 4 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ This pull request still needs...
- [ ] Ran `cargo build`
- [ ] Ran `cargo doc`
- [ ] Ran `nix fmt`
- [ ] Ran `treefmt`

### Github Issue

Expand Down
6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "wasm-interpreter"
version = "0.1.0"
edition = "2021"
rust-version = "1.74.1"
rust-version = "1.76.0"
description = """
A WASM interpreter tailored for safety use-cases, such as automotive and avionics applications
"""
Expand All @@ -23,19 +23,17 @@ libm = "0.2.8"
log = "=0.4.22"

[dev-dependencies]
test-log = {version = "0.2.14", features = ["log"]}
test-log = { version = "0.2.14", features = ["log"] }
env_logger = "0.10.1"
wasmparser = "0.119.0"
itertools = "0.12.0"
wat = "1.0.83"
criterion = { version = "0.5.1", features = ["html_reports"] }


[features]
default = ["hooks"]
hooks = []


[[bench]]
name = "hook_performance_impact"
harness = false
2 changes: 1 addition & 1 deletion requirements/requirements.sdoc
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ RELATIONS:
UID: REQ-17
TITLE: Minimum Supported Rust Version (MSRV)
STATEMENT: >>>
The interpreter shall compile on Rust ``1.74.1`` and later versions
The interpreter shall compile on Rust ``1.76.0`` and later versions
<<<
RATIONALE: >>>
An MSRV should be clearly stated to specify which toolchain is acceptable.
Expand Down
66 changes: 66 additions & 0 deletions src/core/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod types;
/// A struct for managing and reading WASM bytecode
///
/// Its purpose is to abstract parsing basic WASM values from the bytecode.
#[derive(Clone)]
pub struct WasmReader<'a> {
/// Entire WASM binary as slice
pub full_wasm_binary: &'a [u8],
Expand Down Expand Up @@ -148,10 +149,39 @@ impl<'a> WasmReader<'a> {
pub fn into_inner(self) -> &'a [u8] {
self.full_wasm_binary
}

/// A wrapper function for reads with transaction-like behavior.
///
/// The provided closure will be called with `&mut self` and its result will be returned.
/// However if the closure returns `Err(_)`, `self` will be reset as if the closure was never called.
#[allow(dead_code)]
pub fn handle_transaction<T, E>(
&mut self,
f: impl FnOnce(&mut WasmReader<'a>) -> core::result::Result<T, E>,
) -> core::result::Result<T, E> {
let original = self.clone();
f(self).inspect_err(|_| {
*self = original;
})
}
}

pub trait WasmReadable: Sized {
/// Reads a new [`Self`] from given [`WasmReader`].
///
/// Note that if this function returns `Err(_)`, the [`WasmReader`] may still have been advanced,
/// which may lead to unexpected behaviour.
/// To avoid this consider using the [`WasmReader::handle_transaction`] method to wrap this function call.
fn read(wasm: &mut WasmReader) -> Result<Self>;

/// Like [`read`](WasmReadable::read), but may panic
///
/// Allows to read a [`Self`], directly returning it, instead of a [`Result`].
/// Useful, when prior validation already assures that a [`Self`] can be read.
///
/// # Panics
///
/// Panics if reading a [`Self`] fails.
fn read_unvalidated(wasm: &mut WasmReader) -> Self;
wucke13 marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -194,6 +224,8 @@ pub mod span {

#[cfg(test)]
mod test {
use crate::ValType;

use super::*;
use alloc::vec;

Expand Down Expand Up @@ -315,4 +347,38 @@ mod test {
assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
assert_eq!(wasm_reader.skip(6), Err(Error::Eof));
}

#[test]
fn reader_transaction() {
let bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6];
let mut reader = WasmReader::new(&bytes);

assert_eq!(
reader.handle_transaction(|reader| { reader.strip_bytes::<2>() }),
Ok([0x1, 0x2]),
);

let transaction_result: Result<()> = reader.handle_transaction(|reader| {
assert_eq!(reader.strip_bytes::<2>(), Ok([0x3, 0x4]));

// The exact error type does not matter
Err(Error::InvalidMagic)
});
assert_eq!(transaction_result, Err(Error::InvalidMagic));

assert_eq!(reader.strip_bytes::<3>(), Ok([0x3, 0x4, 0x5]));
}

#[test]
fn reader_transaction_ergonomics() {
let bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6];
let mut reader = WasmReader::new(&bytes);

assert_eq!(reader.handle_transaction(WasmReader::read_u8), Ok(0x1));

assert_eq!(
reader.handle_transaction(ValType::read),
Err(Error::InvalidValType)
);
}
}
14 changes: 14 additions & 0 deletions treefmt.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
{
# Used to find the project root
projectRootFile = "flake.nix";
programs.nixpkgs-fmt.enable = true;
programs.prettier = {
enable = true;
includes = [
"*.css"
"*.html"
"*.js"
"*.json"
"*.json5"
"*.md"
"*.mdx"
"*.toml"
"*.yaml"
"*.yml"
];
settings = {
plugins = [
"${pkgs.nodePackages.prettier-plugin-toml}/lib/node_modules/prettier-plugin-toml/lib/index.js"
];
};
};
programs.rustfmt.enable = true;
}
17 changes: 0 additions & 17 deletions treefmt.toml

This file was deleted.