Skip to content

Commit

Permalink
Enable fuzzing for Pulley & Winch (bytecodealliance#9966)
Browse files Browse the repository at this point in the history
* Enable fuzzing for Pulley & Winch

This commit refactors the `wasmtime-fuzzing` crate to enable fuzzing the
Pulley interpreter and the Winch compiler more often. Winch has been
feature-complete for much of wasm for a good amount of time now and
Pulley now supports many wasm proposals as well. Both strategies have
wasm proposals that are still disabled, however.

I've run fuzzers for a bit locally and haven't turned up too too much,
but I'm sure OSS-Fuzz will chastise me and tell me all the places I'm
forgetting to add various configs and tweaks.

* Fix test build
  • Loading branch information
alexcrichton authored Jan 13, 2025
1 parent b3b5094 commit c78d44e
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 39 deletions.
2 changes: 1 addition & 1 deletion crates/fuzzing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ target-lexicon = { workspace = true }
tempfile = "3.3.0"
wasmparser = { workspace = true }
wasmprinter = { workspace = true }
wasmtime = { workspace = true, features = ['default', 'winch', 'gc', 'memory-protection-keys', 'signals-based-traps'] }
wasmtime = { workspace = true, features = ['default', 'winch', 'gc', 'memory-protection-keys', 'signals-based-traps', 'pulley'] }
wasmtime-wast = { workspace = true, features = ['component-model'] }
wasm-encoder = { workspace = true }
wasm-smith = { workspace = true }
Expand Down
89 changes: 59 additions & 30 deletions crates/fuzzing/src/generators/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ impl Config {
InstanceAllocationStrategy::Pooling(_)
),
compiler: match self.wasmtime.compiler_strategy {
CompilerStrategy::Cranelift => wasmtime_wast_util::Compiler::CraneliftNative,
CompilerStrategy::CraneliftNative => wasmtime_wast_util::Compiler::CraneliftNative,
CompilerStrategy::CraneliftPulley => wasmtime_wast_util::Compiler::CraneliftPulley,
CompilerStrategy::Winch => wasmtime_wast_util::Compiler::Winch,
},
}
Expand Down Expand Up @@ -281,8 +282,11 @@ impl Config {
}

let compiler_strategy = &self.wasmtime.compiler_strategy;
let cranelift_strategy = *compiler_strategy == CompilerStrategy::Cranelift;
cfg.strategy(self.wasmtime.compiler_strategy.to_wasmtime());
let cranelift_strategy = match compiler_strategy {
CompilerStrategy::CraneliftNative | CompilerStrategy::CraneliftPulley => true,
CompilerStrategy::Winch => false,
};
self.wasmtime.compiler_strategy.configure(&mut cfg);
cfg.collector(self.wasmtime.collector.to_wasmtime());

self.wasmtime.codegen.configure(&mut cfg);
Expand Down Expand Up @@ -560,23 +564,32 @@ impl WasmtimeConfig {
config: &mut wasm_smith::Config,
u: &mut Unstructured<'_>,
) -> arbitrary::Result<()> {
// Winch doesn't support the same set of wasm proposal as Cranelift at
// this time, so if winch is selected be sure to disable wasm proposals
// in `Config` to ensure that Winch can compile the module that
// wasm-smith generates.
if let CompilerStrategy::Winch = self.compiler_strategy {
config.simd_enabled = false;
config.relaxed_simd_enabled = false;
config.gc_enabled = false;
config.threads_enabled = false;
config.tail_call_enabled = false;
config.reference_types_enabled = false;

// Tuning the following engine options is currently not supported
// by Winch.
self.signals_based_traps = true;
self.table_lazy_init = true;
self.debug_info = false;
match self.compiler_strategy {
CompilerStrategy::CraneliftNative => {}

// Winch doesn't support the same set of wasm proposal as Cranelift
// at this time, so if winch is selected be sure to disable wasm
// proposals in `Config` to ensure that Winch can compile the
// module that wasm-smith generates.
CompilerStrategy::Winch => {
config.simd_enabled = false;
config.relaxed_simd_enabled = false;
config.gc_enabled = false;
config.threads_enabled = false;
config.tail_call_enabled = false;
config.reference_types_enabled = false;

// Tuning the following engine options is currently not supported
// by Winch.
self.signals_based_traps = true;
self.table_lazy_init = true;
self.debug_info = false;
}

CompilerStrategy::CraneliftPulley => {
config.simd_enabled = false;
config.threads_enabled = false;
}
}

// Forcibly don't use the `CustomUnaligned` memory configuration when
Expand Down Expand Up @@ -745,27 +758,43 @@ impl RegallocAlgorithm {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// Compiler to use.
pub enum CompilerStrategy {
/// Cranelift compiler.
Cranelift,
/// Cranelift compiler for the native architecture.
CraneliftNative,
/// Winch compiler.
Winch,
/// Cranelift compiler for the native architecture.
CraneliftPulley,
}

impl CompilerStrategy {
fn to_wasmtime(&self) -> wasmtime::Strategy {
/// Configures `config` to use this compilation strategy
pub fn configure(&self, config: &mut wasmtime::Config) {
match self {
CompilerStrategy::Cranelift => wasmtime::Strategy::Cranelift,
CompilerStrategy::Winch => wasmtime::Strategy::Winch,
CompilerStrategy::CraneliftNative => {
config.strategy(wasmtime::Strategy::Cranelift);
}
CompilerStrategy::Winch => {
config.strategy(wasmtime::Strategy::Winch);
}
CompilerStrategy::CraneliftPulley => {
config
.strategy(wasmtime::Strategy::Cranelift)
.target("pulley64")
.unwrap();
}
}
}
}

impl Arbitrary<'_> for CompilerStrategy {
fn arbitrary(_: &mut Unstructured<'_>) -> arbitrary::Result<Self> {
// NB: Winch isn't selected here yet as it doesn't yet implement all the
// compiler features for things such as trampolines, so it's only used
// on fuzz targets that don't need those trampolines.
Ok(Self::Cranelift)
fn arbitrary(u: &mut Unstructured<'_>) -> arbitrary::Result<Self> {
// Favor fuzzing native cranelift, but if allowed also enable
// winch/pulley.
match u.int_in_range(0..=19)? {
1 => Ok(Self::CraneliftPulley),
2 => Ok(Self::Winch),
_ => Ok(Self::CraneliftNative),
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/fuzzing/src/oracles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ mod tests {
) -> bool {
let mut rng = SmallRng::seed_from_u64(0);
let mut buf = vec![0; 2048];
let n = 2000;
let n = 3000;
for _ in 0..n {
rng.fill_bytes(&mut buf);
let mut u = Unstructured::new(&buf);
Expand Down
14 changes: 11 additions & 3 deletions crates/fuzzing/src/oracles/diff_wasmtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ impl WasmtimeEngine {
impl DiffEngine for WasmtimeEngine {
fn name(&self) -> &'static str {
match self.config.wasmtime.compiler_strategy {
CompilerStrategy::Cranelift => "wasmtime",
CompilerStrategy::CraneliftNative => "wasmtime",
CompilerStrategy::Winch => "winch",
CompilerStrategy::CraneliftPulley => "pulley",
}
}

Expand Down Expand Up @@ -244,9 +245,16 @@ mod tests {
use super::*;

#[test]
fn smoke_cranelift() {
fn smoke_cranelift_native() {
crate::oracles::engine::smoke_test_engine(|u, config| {
WasmtimeEngine::new(u, config, CompilerStrategy::Cranelift)
WasmtimeEngine::new(u, config, CompilerStrategy::CraneliftNative)
})
}

#[test]
fn smoke_cranelift_pulley() {
crate::oracles::engine::smoke_test_engine(|u, config| {
WasmtimeEngine::new(u, config, CompilerStrategy::CraneliftPulley)
})
}

Expand Down
11 changes: 10 additions & 1 deletion crates/fuzzing/src/oracles/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ pub fn build(
config: &mut Config,
) -> arbitrary::Result<Option<Box<dyn DiffEngine>>> {
let engine: Box<dyn DiffEngine> = match name {
"wasmtime" => Box::new(WasmtimeEngine::new(u, config, CompilerStrategy::Cranelift)?),
"wasmtime" => Box::new(WasmtimeEngine::new(
u,
config,
CompilerStrategy::CraneliftNative,
)?),
"pulley" => Box::new(WasmtimeEngine::new(
u,
config,
CompilerStrategy::CraneliftPulley,
)?),
"wasmi" => Box::new(WasmiEngine::new(config)),

#[cfg(target_arch = "x86_64")]
Expand Down
13 changes: 10 additions & 3 deletions fuzz/fuzz_targets/differential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fuzz_target!(|data: &[u8]| {
// environment variables.
let allowed_engines = build_allowed_env_list(
parse_env_list("ALLOWED_ENGINES"),
&["wasmtime", "wasmi", "spec", "v8", "winch"],
&["wasmtime", "wasmi", "spec", "v8", "winch", "pulley"],
);
let allowed_modules = build_allowed_env_list(
parse_env_list("ALLOWED_MODULES"),
Expand Down Expand Up @@ -201,6 +201,7 @@ struct RuntimeStats {
spec: AtomicUsize,
wasmtime: AtomicUsize,
winch: AtomicUsize,
pulley: AtomicUsize,

// Counters for which style of module is chosen
wasm_smith_modules: AtomicUsize,
Expand All @@ -218,6 +219,7 @@ impl RuntimeStats {
spec: AtomicUsize::new(0),
wasmtime: AtomicUsize::new(0),
winch: AtomicUsize::new(0),
pulley: AtomicUsize::new(0),
wasm_smith_modules: AtomicUsize::new(0),
single_instruction_modules: AtomicUsize::new(0),
}
Expand All @@ -241,14 +243,18 @@ impl RuntimeStats {
let wasmi = self.wasmi.load(SeqCst);
let wasmtime = self.wasmtime.load(SeqCst);
let winch = self.winch.load(SeqCst);
let total = v8 + spec + wasmi + wasmtime + winch;
let pulley = self.pulley.load(SeqCst);
let total = v8 + spec + wasmi + wasmtime + winch + pulley;
println!(
"\twasmi: {:.02}%, spec: {:.02}%, wasmtime: {:.02}%, v8: {:.02}%, winch: {:.02}%",
"\twasmi: {:.02}%, spec: {:.02}%, wasmtime: {:.02}%, v8: {:.02}%, \
winch: {:.02}, \
pulley: {:.02}%",
wasmi as f64 / total as f64 * 100f64,
spec as f64 / total as f64 * 100f64,
wasmtime as f64 / total as f64 * 100f64,
v8 as f64 / total as f64 * 100f64,
winch as f64 / total as f64 * 100f64,
pulley as f64 / total as f64 * 100f64,
);

let wasm_smith = self.wasm_smith_modules.load(SeqCst);
Expand All @@ -268,6 +274,7 @@ impl RuntimeStats {
"spec" => self.spec.fetch_add(1, SeqCst),
"v8" => self.v8.fetch_add(1, SeqCst),
"winch" => self.winch.fetch_add(1, SeqCst),
"pulley" => self.pulley.fetch_add(1, SeqCst),
_ => return,
};
}
Expand Down

0 comments on commit c78d44e

Please sign in to comment.