You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

79 lines
2.5 KiB

#![no_main]
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
use wasmtime_fuzzing::generators::Config;
use wasmtime_fuzzing::oracles::{instantiate, Timeout};
use wasmtime_fuzzing::single_module_fuzzer::KnownValid;
wasmtime_fuzzing::single_module_fuzzer!(execute gen_module);
#[derive(Debug)]
struct InstantiateInput {
config: Config,
timeout: Timeout,
}
impl<'a> Arbitrary<'a> for InstantiateInput {
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
let mut config: Config = u.arbitrary()?;
// Pick either fuel, duration-based, or module-based timeout. Note that
// the module-based timeout is implemented with wasm-smith's
// `ensure_termination` option.
let timeout = if u.arbitrary()? {
config.generate_timeout(u)?
} else {
Timeout::None
};
Ok(InstantiateInput { config, timeout })
}
}
fn execute(
module: &[u8],
known_valid: KnownValid,
mut input: InstantiateInput,
u: &mut Unstructured<'_>,
) -> Result<()> {
let timeout = match input.timeout {
// If the input module isn't a "known valid" module then it can't be
// relied on self-regulating itself, so force a timeout via epochs/fuel
// in the configuration.
Timeout::None if known_valid == KnownValid::No => input.config.generate_timeout(u)?,
other => other,
};
instantiate(module, known_valid, &input.config, timeout);
Ok(())
}
fn gen_module(
input: &mut InstantiateInput,
u: &mut Unstructured<'_>,
) -> Result<(Vec<u8>, KnownValid)> {
// With a small-ish chance take raw fuzz input and put it in the module to
// stress module compilation/validation. In such a situation we can't use
// `ensure_termination` in wasm-smith so list the timeout as `None` to time
// out via epochs or Wasmtime-level fuel.
//
// Otherwise though if no timeout is configured use wasm-smith fuel to
// ensure termination.
let allow_invalid_funcs = u.ratio(1, 10)?;
let default_fuel = if allow_invalid_funcs {
input.config.module_config.config.allow_invalid_funcs = true;
input.timeout = Timeout::None;
None
} else if let Timeout::None = input.timeout {
Some(1000)
} else {
None
};
let module = input.config.generate(u, default_fuel)?;
let known_valid = if allow_invalid_funcs {
KnownValid::No
} else {
KnownValid::Yes
};
Ok((module.to_bytes(), known_valid))
}