Skip to content

Commit

Permalink
Update wasmi used during fuzzing (#9458)
Browse files Browse the repository at this point in the history
* Fix differential fuzzing with multi-memory and pooling

Fix an issue found during fuzzing where when multi-memory and the
pooling allocator are enabled then if MPK is detected and found the
total number of memories needs to be increased because stores belong in
a single stripe.

* Update wasmi used in fuzzing

Pulls in differential fuzzing support for multi-memory
  • Loading branch information
alexcrichton authored Oct 11, 2024
1 parent 9b2e972 commit 460a4c0
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 69 deletions.
68 changes: 54 additions & 14 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/fuzzing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ wasm-encoder = { workspace = true }
wasm-smith = { workspace = true }
wasm-mutate = { workspace = true }
wasm-spec-interpreter = { path = "./wasm-spec-interpreter", optional = true }
wasmi = "0.31.1"
wasmi = "0.38.0"
futures = { workspace = true }

# We rely on precompiled v8 binaries, but rusty-v8 doesn't have a precompiled
Expand Down
8 changes: 7 additions & 1 deletion crates/fuzzing/src/generators/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use anyhow::Result;
use arbitrary::{Arbitrary, Unstructured};
use std::sync::Arc;
use std::time::Duration;
use wasmtime::{Engine, Module, Store};
use wasmtime::{Engine, Module, MpkEnabled, Store};

/// Configuration for `wasmtime::Config` and generated modules for a session of
/// fuzzing.
Expand Down Expand Up @@ -78,6 +78,12 @@ impl Config {
pooling.total_memories = config.max_memories as u32;
pooling.max_memory_size = 10 << 16;
pooling.max_memories_per_module = config.max_memories as u32;
if pooling.memory_protection_keys == MpkEnabled::Auto
&& pooling.max_memory_protection_keys > 1
{
pooling.total_memories =
pooling.total_memories * (pooling.max_memory_protection_keys as u32);
}

pooling.total_tables = config.max_tables as u32;
pooling.table_elements = 1_000;
Expand Down
3 changes: 2 additions & 1 deletion crates/fuzzing/src/generators/pooling_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl PoolingAllocationConfig {
cfg.async_stack_keep_resident(self.async_stack_keep_resident);

cfg.memory_protection_keys(self.memory_protection_keys);
cfg.max_memory_protection_keys(self.max_memory_protection_keys);

cfg
}
Expand Down Expand Up @@ -115,7 +116,7 @@ impl<'a> Arbitrary<'a> for PoolingAllocationConfig {
async_stack_keep_resident: u.int_in_range(0..=1 << 20)?,

memory_protection_keys: *u.choose(&[MpkEnabled::Auto, MpkEnabled::Disable])?,
max_memory_protection_keys: u.int_in_range(0..=20)?,
max_memory_protection_keys: u.int_in_range(1..=20)?,
})
}
}
87 changes: 35 additions & 52 deletions crates/fuzzing/src/oracles/diff_wasmi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ impl WasmiEngine {
config.exceptions_enabled = false;
config.gc_enabled = false;
config.wide_arithmetic_enabled = false;
config.max_memories = config.max_memories.min(1);
config.min_memories = config.min_memories.min(1);

let mut wasmi_config = wasmi::Config::default();
wasmi_config
Expand All @@ -35,11 +33,32 @@ impl WasmiEngine {
.wasm_bulk_memory(config.bulk_memory_enabled)
.wasm_reference_types(config.reference_types_enabled)
.wasm_tail_call(config.tail_call_enabled)
.wasm_multi_memory(config.max_memories > 1)
.wasm_extended_const(true);
Self {
engine: wasmi::Engine::new(&wasmi_config),
}
}

fn trap_code(&self, err: &Error) -> Option<wasmi::core::TrapCode> {
let err = err.downcast_ref::<wasmi::Error>()?;
if let Some(code) = err.as_trap_code() {
return Some(code);
}

match err.kind() {
wasmi::errors::ErrorKind::Instantiation(
wasmi::errors::InstantiationError::ElementSegmentDoesNotFit { .. },
) => Some(wasmi::core::TrapCode::TableOutOfBounds),
wasmi::errors::ErrorKind::Memory(wasmi::errors::MemoryError::OutOfBoundsAccess) => {
Some(wasmi::core::TrapCode::MemoryOutOfBounds)
}
_ => {
log::trace!("unknown wasmi error: {:?}", err.kind());
None
}
}
}
}

impl DiffEngine for WasmiEngine {
Expand All @@ -59,53 +78,17 @@ impl DiffEngine for WasmiEngine {
}

fn assert_error_match(&self, trap: &Trap, err: &Error) {
// Acquire a `wasmi::Trap` from the wasmi error which we'll use to
// assert that it has the same kind of trap as the wasmtime-based trap.
let wasmi = match err.downcast_ref::<wasmi::Error>() {
Some(wasmi::Error::Trap(trap)) => trap,

// Out-of-bounds data segments turn into this category which
// Wasmtime reports as a `MemoryOutOfBounds`.
Some(wasmi::Error::Memory(msg)) => {
assert_eq!(
*trap,
Trap::MemoryOutOfBounds,
"wasmtime error did not match wasmi: {msg}"
);
return;
}

// Ignore this for now, looks like "elements segment does not fit"
// falls into this category and to avoid doing string matching this
// is just ignored.
Some(wasmi::Error::Instantiation(msg)) => {
log::debug!("ignoring wasmi instantiation error: {msg}");
return;
}

Some(other) => panic!("unexpected wasmi error: {other}"),

None => err
.downcast_ref::<wasmi::core::Trap>()
.expect(&format!("not a trap: {err:?}")),
};
assert!(wasmi.trap_code().is_some());
assert_eq!(
wasmi_to_wasmtime_trap_code(wasmi.trap_code().unwrap()),
*trap
);
match self.trap_code(err) {
Some(code) => assert_eq!(wasmi_to_wasmtime_trap_code(code), *trap),
None => panic!("unexpected wasmi error {err:?}"),
}
}

fn is_stack_overflow(&self, err: &Error) -> bool {
let trap = match err.downcast_ref::<wasmi::Error>() {
Some(wasmi::Error::Trap(trap)) => trap,
Some(_) => return false,
None => match err.downcast_ref::<wasmi::core::Trap>() {
Some(trap) => trap,
None => return false,
},
};
matches!(trap.trap_code(), Some(wasmi::core::TrapCode::StackOverflow))
matches!(
self.trap_code(err),
Some(wasmi::core::TrapCode::StackOverflow)
)
}
}

Expand Down Expand Up @@ -150,7 +133,7 @@ impl DiffInstance for WasmiInstance {
.and_then(wasmi::Extern::into_func)
.unwrap();
let arguments: Vec<_> = arguments.iter().map(|x| x.into()).collect();
let mut results = vec![wasmi::Value::I32(0); result_tys.len()];
let mut results = vec![wasmi::Val::I32(0); result_tys.len()];
function
.call(&mut self.store, &arguments, &mut results)
.context("wasmi function trap")?;
Expand Down Expand Up @@ -183,9 +166,9 @@ impl DiffInstance for WasmiInstance {
}
}

impl From<&DiffValue> for wasmi::Value {
impl From<&DiffValue> for wasmi::Val {
fn from(v: &DiffValue) -> Self {
use wasmi::Value as WasmiValue;
use wasmi::Val as WasmiValue;
match *v {
DiffValue::I32(n) => WasmiValue::I32(n),
DiffValue::I64(n) => WasmiValue::I64(n),
Expand All @@ -205,9 +188,9 @@ impl From<&DiffValue> for wasmi::Value {
}
}

impl From<wasmi::Value> for DiffValue {
fn from(value: wasmi::Value) -> Self {
use wasmi::Value as WasmiValue;
impl From<wasmi::Val> for DiffValue {
fn from(value: wasmi::Val) -> Self {
use wasmi::Val as WasmiValue;
match value {
WasmiValue::I32(n) => DiffValue::I32(n),
WasmiValue::I64(n) => DiffValue::I64(n),
Expand Down
6 changes: 6 additions & 0 deletions supply-chain/audits.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,12 @@ Most of the rest of the changes are adding some new unstable features which
aren't enabled by default.
"""

[[audits.smallvec]]
who = "Alex Crichton <[email protected]>"
criteria = "safe-to-deploy"
delta = "1.11.0 -> 1.13.2"
notes = "Mostly minor updates, the one semi-substantial update looks good."

[[audits.socket2]]
who = "Alex Crichton <[email protected]>"
criteria = "safe-to-deploy"
Expand Down
7 changes: 7 additions & 0 deletions supply-chain/imports.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,13 @@ user-id = 2915
user-login = "Amanieu"
user-name = "Amanieu d'Antras"

[[publisher.libm]]
version = "0.2.8"
when = "2023-10-06"
user-id = 2915
user-login = "Amanieu"
user-name = "Amanieu d'Antras"

[[publisher.linux-raw-sys]]
version = "0.3.8"
when = "2023-05-19"
Expand Down

0 comments on commit 460a4c0

Please sign in to comment.