diff --git a/Cargo.lock b/Cargo.lock index 9f736c8c08..59bb30fc78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3446,18 +3446,18 @@ checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" [[package]] name = "wasm-encoder" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3fb3541f4cdc05f0eacd7ce5544d69a4cc3e922ef1e7f37c1e7cb8b1e8e66" +checksum = "2caacc74c68c74f0008c4055cdf509c43e623775eaf73323bb818dcf666ed9bd" dependencies = [ "leb128", ] [[package]] name = "wasm-smith" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b73bf3c616211529547284f12db7bb1e4d9bca11c738533490546239bbd120" +checksum = "f93b328ed4cef568449c185c89816ad587b172681af3b3d57f63178213ae36b4" dependencies = [ "arbitrary", "indexmap", diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 7e6e5a014c..beb35779b0 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -17,8 +17,8 @@ wasmparser = "0.80" wasmprinter = "0.2.28" wasmtime = { path = "../wasmtime" } wasmtime-wast = { path = "../wast" } -wasm-encoder = "0.5.0" -wasm-smith = "0.5.0" +wasm-encoder = "0.6.0" +wasm-smith = "0.6.0" wasmi = "0.7.0" [dev-dependencies] diff --git a/crates/fuzzing/src/generators.rs b/crates/fuzzing/src/generators.rs index 48fee8e6e9..bfbf914289 100644 --- a/crates/fuzzing/src/generators.rs +++ b/crates/fuzzing/src/generators.rs @@ -116,3 +116,37 @@ impl<'a> Arbitrary<'a> for SpecTest { (1, Some(std::mem::size_of::())) } } + +/// Type alias for wasm-smith generated modules using wasmtime's default +/// configuration. +pub type GeneratedModule = wasm_smith::ConfiguredModule; + +/// Wasmtime-specific default configuration for wasm-smith-generated modules. +#[derive(Arbitrary, Clone, Debug)] +pub struct WasmtimeDefaultConfig; + +impl wasm_smith::Config for WasmtimeDefaultConfig { + // Allow multi-memory to get exercised + fn max_memories(&self) -> usize { + 2 + } + + // Allow multi-table (reference types) to get exercised + fn max_tables(&self) -> usize { + 4 + } + + // Turn some wasm features default-on for those that have a finished + // implementation in Wasmtime. + fn simd_enabled(&self) -> bool { + true + } + + fn reference_types_enabled(&self) -> bool { + true + } + + fn bulk_memory_enabled(&self) -> bool { + true + } +} diff --git a/crates/fuzzing/src/generators/api.rs b/crates/fuzzing/src/generators/api.rs index 1f47765dff..3e3561ebbb 100644 --- a/crates/fuzzing/src/generators/api.rs +++ b/crates/fuzzing/src/generators/api.rs @@ -17,7 +17,6 @@ use arbitrary::{Arbitrary, Unstructured}; use std::collections::BTreeMap; use std::mem; -use wasm_smith::Module; use wasmparser::*; #[derive(Arbitrary, Debug)] @@ -40,11 +39,24 @@ pub enum ApiCall { ConfigInterruptable(bool), EngineNew, StoreNew, - ModuleNew { id: usize, wasm: Module }, - ModuleDrop { id: usize }, - InstanceNew { id: usize, module: usize }, - InstanceDrop { id: usize }, - CallExportedFunc { instance: usize, nth: usize }, + ModuleNew { + id: usize, + wasm: super::GeneratedModule, + }, + ModuleDrop { + id: usize, + }, + InstanceNew { + id: usize, + module: usize, + }, + InstanceDrop { + id: usize, + }, + CallExportedFunc { + instance: usize, + nth: usize, + }, } use ApiCall::*; @@ -107,7 +119,7 @@ impl<'a> Arbitrary<'a> for ApiCalls { if swarm.module_new { choices.push(|input, scope| { let id = scope.next_id(); - let mut wasm = Module::arbitrary(input)?; + let mut wasm = super::GeneratedModule::arbitrary(input)?; wasm.ensure_termination(1000); let predicted_rss = predict_rss(&wasm.to_bytes()).unwrap_or(0); scope.modules.insert(id, predicted_rss); @@ -175,7 +187,7 @@ impl<'a> Arbitrary<'a> for ApiCalls { // We can generate arbitrary `WasmOptTtf` instances, which have // no upper bound on the number of bytes they consume. This sets // the upper bound to `None`. - ::size_hint(depth), + ::size_hint(depth), ) }) } diff --git a/crates/fuzzing/src/generators/table_ops.rs b/crates/fuzzing/src/generators/table_ops.rs index adb2373fea..c3e36f5b03 100644 --- a/crates/fuzzing/src/generators/table_ops.rs +++ b/crates/fuzzing/src/generators/table_ops.rs @@ -4,7 +4,7 @@ use arbitrary::Arbitrary; use std::ops::Range; use wasm_encoder::{ CodeSection, EntityType, Export, ExportSection, Function, FunctionSection, ImportSection, - Instruction, Limits, Module, TableSection, TableType, TypeSection, ValType, + Instruction, Module, TableSection, TableType, TypeSection, ValType, }; /// A description of a Wasm module that makes a series of `externref` table @@ -57,10 +57,8 @@ impl TableOps { let mut tables = TableSection::new(); tables.table(TableType { element_type: ValType::ExternRef, - limits: Limits { - min: self.table_size(), - max: None, - }, + minimum: self.table_size(), + maximum: None, }); // Encode the types for all functions that we are using. diff --git a/crates/fuzzing/src/lib.rs b/crates/fuzzing/src/lib.rs index 7ef3382411..3ad094a6ef 100644 --- a/crates/fuzzing/src/lib.rs +++ b/crates/fuzzing/src/lib.rs @@ -39,6 +39,8 @@ pub fn fuzz_default_config(strategy: wasmtime::Strategy) -> anyhow::Result u32 { + fn max_memory_pages(&self, _is_64: bool) -> u64 { 1 } diff --git a/crates/fuzzing/src/oracles/dummy.rs b/crates/fuzzing/src/oracles/dummy.rs index 068aa65c46..fc426e7c6e 100644 --- a/crates/fuzzing/src/oracles/dummy.rs +++ b/crates/fuzzing/src/oracles/dummy.rs @@ -39,7 +39,7 @@ pub fn dummy_extern(store: &mut Store, ty: ExternType) -> Result { Ok(match ty { ExternType::Func(func_ty) => Extern::Func(dummy_func(store, func_ty)), ExternType::Global(global_ty) => Extern::Global(dummy_global(store, global_ty)), - ExternType::Table(table_ty) => Extern::Table(dummy_table(store, table_ty)), + ExternType::Table(table_ty) => Extern::Table(dummy_table(store, table_ty)?), ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(store, mem_ty)?), ExternType::Instance(instance_ty) => Extern::Instance(dummy_instance(store, instance_ty)?), ExternType::Module(module_ty) => Extern::Module(dummy_module(store.engine(), module_ty)), @@ -81,9 +81,9 @@ pub fn dummy_global(store: &mut Store, ty: GlobalType) -> Global { } /// Construct a dummy table for the given table type. -pub fn dummy_table(store: &mut Store, ty: TableType) -> Table { +pub fn dummy_table(store: &mut Store, ty: TableType) -> Result { let init_val = dummy_value(ty.element().clone()); - Table::new(store, ty, init_val).unwrap() + Table::new(store, ty, init_val) } /// Construct a dummy memory for the given memory type. @@ -393,7 +393,8 @@ mod tests { let table = dummy_table( &mut store, TableType::new(ValType::ExternRef, Limits::at_least(10)), - ); + ) + .unwrap(); assert_eq!(table.size(&store), 10); for i in 0..10 { assert!(table diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index c740016b13..20eb657c80 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -20,7 +20,7 @@ target-lexicon = "0.12" peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true } wasmtime = { path = "../crates/wasmtime" } wasmtime-fuzzing = { path = "../crates/fuzzing" } -wasm-smith = "0.5.0" +wasm-smith = "0.6.0" [features] # Leave a stub feature with no side-effects in place for now: the OSS-Fuzz diff --git a/fuzz/fuzz_targets/differential.rs b/fuzz/fuzz_targets/differential.rs index 9b92d7998f..4301786992 100644 --- a/fuzz/fuzz_targets/differential.rs +++ b/fuzz/fuzz_targets/differential.rs @@ -6,7 +6,7 @@ use wasmtime_fuzzing::{generators, oracles}; fuzz_target!(|data: ( generators::DifferentialConfig, generators::DifferentialConfig, - wasm_smith::Module, + generators::GeneratedModule, )| { let (lhs, rhs, mut wasm) = data; wasm.ensure_termination(1000); diff --git a/fuzz/fuzz_targets/instantiate-swarm.rs b/fuzz/fuzz_targets/instantiate-swarm.rs index b534cc4970..35cab80dba 100644 --- a/fuzz/fuzz_targets/instantiate-swarm.rs +++ b/fuzz/fuzz_targets/instantiate-swarm.rs @@ -1,24 +1,41 @@ #![no_main] +use libfuzzer_sys::arbitrary::{Result, Unstructured}; use libfuzzer_sys::fuzz_target; use std::time::Duration; -use wasm_smith::{Config, ConfiguredModule, SwarmConfig}; +use wasm_smith::{ConfiguredModule, SwarmConfig}; use wasmtime::Strategy; use wasmtime_fuzzing::oracles::{self, Timeout}; -fuzz_target!(|pair: (bool, ConfiguredModule)| { - let (timeout_with_time, module) = pair; - let mut cfg = wasmtime_fuzzing::fuzz_default_config(Strategy::Auto).unwrap(); - cfg.wasm_multi_memory(true); - cfg.wasm_module_linking(module.config().module_linking_enabled()); - oracles::instantiate_with_config( - &module.to_bytes(), - true, - cfg, - if timeout_with_time { - Timeout::Time(Duration::from_secs(20)) - } else { - Timeout::Fuel(100_000) - }, - ); +fuzz_target!(|data: &[u8]| { + // errors in `run` have to do with not enough input in `data`, which we + // ignore here since it doesn't affect how we'd like to fuzz. + drop(run(data)); }); + +fn run(data: &[u8]) -> Result<()> { + let mut u = Unstructured::new(data); + let timeout = if u.arbitrary()? { + Timeout::Time(Duration::from_secs(20)) + } else { + Timeout::Fuel(100_000) + }; + + // Further configure `SwarmConfig` after we generate one to enable features + // that aren't otherwise enabled by default. We want to test all of these in + // Wasmtime. + let mut config: SwarmConfig = u.arbitrary()?; + config.simd_enabled = u.arbitrary()?; + config.module_linking_enabled = u.arbitrary()?; + // Don't generate modules that allocate more than 6GB + config.max_memory_pages = 6 << 30; + let module = ConfiguredModule::new(config.clone(), &mut u)?; + + let mut cfg = wasmtime_fuzzing::fuzz_default_config(Strategy::Auto).unwrap(); + cfg.wasm_multi_memory(config.max_memories > 1); + cfg.wasm_module_linking(config.module_linking_enabled); + cfg.wasm_simd(config.simd_enabled); + + oracles::instantiate_with_config(&module.to_bytes(), true, cfg, timeout); + Ok(()) +} diff --git a/fuzz/fuzz_targets/instantiate-wasm-smith.rs b/fuzz/fuzz_targets/instantiate-wasm-smith.rs index 546a198ff0..b21cda78f3 100644 --- a/fuzz/fuzz_targets/instantiate-wasm-smith.rs +++ b/fuzz/fuzz_targets/instantiate-wasm-smith.rs @@ -1,11 +1,10 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use wasm_smith::Module; use wasmtime::Strategy; -use wasmtime_fuzzing::oracles; +use wasmtime_fuzzing::{generators::GeneratedModule, oracles}; -fuzz_target!(|module: Module| { +fuzz_target!(|module: GeneratedModule| { let mut module = module; module.ensure_termination(1000); let wasm_bytes = module.to_bytes();