Files
wasmtime/crates/fuzzing/src/generators/module.rs

72 lines
2.4 KiB
Rust

//! Generate a Wasm module and the configuration for generating it.
use arbitrary::{Arbitrary, Unstructured};
use wasm_smith::SwarmConfig;
/// Default module-level configuration for fuzzing Wasmtime.
///
/// Internally this uses `wasm-smith`'s own `SwarmConfig` but we further refine
/// the defaults here as well.
#[derive(Debug, Clone)]
pub struct ModuleConfig {
#[allow(missing_docs)]
pub config: SwarmConfig,
}
impl<'a> Arbitrary<'a> for ModuleConfig {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<ModuleConfig> {
let mut config = SwarmConfig::arbitrary(u)?;
// Allow multi-memory but make it unlikely
if u.ratio(1, 20)? {
config.max_memories = config.max_memories.max(2);
} else {
config.max_memories = 1;
}
// Allow multi-table by default.
if config.reference_types_enabled {
config.max_tables = config.max_tables.max(4);
}
// Allow enabling some various wasm proposals by default. Note that
// these are all unconditionally turned off even with
// `SwarmConfig::arbitrary`.
config.memory64_enabled = u.ratio(1, 20)?;
// Allow the threads proposal if memory64 is not already enabled. FIXME:
// to allow threads and memory64 to coexist, see
// https://github.com/bytecodealliance/wasmtime/issues/4267.
config.threads_enabled = !config.memory64_enabled && u.ratio(1, 20)?;
// We get better differential execution when we disallow traps, so we'll
// do that most of the time.
config.disallow_traps = u.ratio(9, 10)?;
Ok(ModuleConfig { config })
}
}
impl ModuleConfig {
/// Uses this configuration and the supplied source of data to generate a
/// Wasm module.
///
/// If a `default_fuel` is provided, the resulting module will be configured
/// to ensure termination; as doing so will add an additional global to the
/// module, the pooling allocator, if configured, must also have its globals
/// limit updated.
pub fn generate(
&self,
input: &mut Unstructured<'_>,
default_fuel: Option<u32>,
) -> arbitrary::Result<wasm_smith::Module> {
let mut module = wasm_smith::Module::new(self.config.clone(), input)?;
if let Some(default_fuel) = default_fuel {
module.ensure_termination(default_fuel);
}
Ok(module)
}
}