Skip to content

Commit

Permalink
Add fuzzing config support for different collectors
Browse files Browse the repository at this point in the history
  • Loading branch information
fitzgen committed Oct 18, 2024
1 parent f19e1dc commit 7102948
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
17 changes: 17 additions & 0 deletions crates/fuzzing/src/generators/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl Config {
let compiler_strategy = &self.wasmtime.compiler_strategy;
let cranelift_strategy = *compiler_strategy == CompilerStrategy::Cranelift;
cfg.strategy(self.wasmtime.compiler_strategy.to_wasmtime());
cfg.collector(self.wasmtime.collector.to_wasmtime());

self.wasmtime.codegen.configure(&mut cfg);

Expand Down Expand Up @@ -429,6 +430,7 @@ pub struct WasmtimeConfig {
native_unwind_info: bool,
/// Configuration for the compiler to use.
pub compiler_strategy: CompilerStrategy,
collector: Collector,
table_lazy_init: bool,

/// Whether or not fuzzing should enable PCC.
Expand Down Expand Up @@ -637,3 +639,18 @@ impl Arbitrary<'_> for CompilerStrategy {
Ok(Self::Cranelift)
}
}

#[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Collector {
DeferredReferenceCounting,
Null,
}

impl Collector {
fn to_wasmtime(&self) -> wasmtime::Collector {
match self {
Collector::DeferredReferenceCounting => wasmtime::Collector::DeferredReferenceCounting,
Collector::Null => wasmtime::Collector::Null,
}
}
}
25 changes: 20 additions & 5 deletions crates/fuzzing/src/oracles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,23 +504,38 @@ impl<T, U> DiffEqResult<T, U> {
match (lhs_result, rhs_result) {
(Ok(lhs_result), Ok(rhs_result)) => DiffEqResult::Success(lhs_result, rhs_result),

// Both sides failed. If either one hits a stack overflow then that's an
// engine defined limit which means we can no longer compare the state
// of the two instances, so `None` is returned and nothing else is
// compared.
// Both sides failed. Check that the trap and state at the time of
// failure is the same, when possible.
(Err(lhs), Err(rhs)) => {
let err = match rhs.downcast::<Trap>() {
Ok(trap) => trap,

// For general, unknown errors, we can't rely on this being
// a deterministic Wasm failure that both engines handled
// identically, leaving Wasm in identical states. We could
// just as easily be hitting engine-specific failures, like
// different implementation-defined limits. So simply report
// failure and move on to the next test.
Err(err) => {
log::debug!("rhs failed: {err:?}");
return DiffEqResult::Failed;
}
};
let poisoned = err == Trap::StackOverflow || lhs_engine.is_stack_overflow(&lhs);

// Even some traps are nondeterministic, and we can't rely on
// the errors matching or leaving Wasm in the same state.
let poisoned =
// Allocations being too large for the GC are
// implementation-defined.
err == Trap::AllocationTooLarge
// Stack size, and therefore when overflow happens, is
// implementation-defined.
|| err == Trap::StackOverflow
|| lhs_engine.is_stack_overflow(&lhs);
if poisoned {
return DiffEqResult::Poisoned;
}

lhs_engine.assert_error_match(&err, &lhs);
DiffEqResult::Failed
}
Expand Down

0 comments on commit 7102948

Please sign in to comment.