#![no_main]
use arbitrary::{Arbitrary, Unstructured};
use libfuzzer_sys::fuzz_target;
use wasmi::{Config, Engine, Module};
use wasmi_fuzz::{FuzzModule, FuzzWasmiConfig, config::ValidationMode};
#[derive(Debug)]
pub struct FuzzInput {
config: FuzzWasmiConfig,
module: FuzzModule,
}
impl<'a> Arbitrary<'a> for FuzzInput {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let config = FuzzWasmiConfig::arbitrary(u)?;
let fuzz_config = wasmi_fuzz::FuzzSmithConfig::arbitrary(u)?;
let module = wasmi_fuzz::FuzzModule::new(fuzz_config, u)?;
Ok(Self { config, module })
}
}
fuzz_target!(|input: FuzzInput| {
let FuzzInput { config, module } = input;
let wasm_source = module.wasm();
let wasm = wasm_source.as_bytes();
let engine_config = Config::from(config);
let engine = Engine::new(&engine_config);
if matches!(config.validation_mode, ValidationMode::Unchecked) {
if Module::validate(&engine, wasm).is_err() {
return;
}
}
let status = match config.validation_mode {
ValidationMode::Checked => Module::new(&engine, wasm),
ValidationMode::Unchecked => {
unsafe { Module::new_unchecked(&engine, wasm) }
}
};
if let Err(err) = status {
let crash_input = wasmi_fuzz::generate_crash_inputs("translate", wasm).unwrap();
panic!(
"\
encountered invalid translation: {err}\n\
\t- crash-report: 0x{crash_input}\n\
"
);
}
});