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.

40 lines
1.3 KiB

Add a fuzzer for async wasm (#8440) * Add a fuzzer for async wasm This commit revives a very old branch of mine to add a fuzzer for Wasmtime in async mode. This work was originally blocked on llvm/llvm-project#53891 and while that's still an issue it now contains a workaround for that issue. Support for async fuzzing required a good deal of refactorings and changes, and the highlights are: * The main part is that new intrinsics, `__sanitizer_{start,finish}_fiber_switch` are now invoked around the stack-switching routines of fibers. This only works on Unix and is set to only compile when ASAN is enabled (otherwise everything is a noop). This required refactoring of things to get it all in just the right way for ASAN since it appears that these functions not only need to be called but more-or-less need to be adjacent to each other in the code. My guess is that while we're switching ASAN is in a "weird state" and it's not ready to run arbitrary code. * Stacks are a problem. The above issue in LLVM outlines how stacks cannot be deallocated at this time because if the deallocated virtual memory is later used for the heap then ASAN will have a false positive about stack overflow. To handle this stacks are specially handled in asan mode by using a special allocation path that never deallocates stacks. This logic additionally applies to the pooling allocator which uses a different stack allocation strategy with ASAN. With all of the above a new fuzzer is added. This fuzzer generates an arbitrary module, selects an arbitrary means of async (e.g. epochs/fuel), and then tries to execute the exports of the module with various values. In general the fuzzer is looking for crashes/panics as opposed to correct answers as there's no oracle here. This is also intended to stress the code used to switch on and off stacks. * Fix non-async build * Remove unused import * Review comments * Fix compile on MIRI * Fix Windows build
7 months ago
#![no_main]
use libfuzzer_sys::arbitrary::{Result, Unstructured};
use libfuzzer_sys::fuzz_target;
use wasmtime_fuzzing::{generators, oracles};
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.
let _ = run_one(data);
});
fn run_one(data: &[u8]) -> Result<()> {
let mut u = Unstructured::new(data);
let mut config: generators::Config = u.arbitrary()?;
// Try to ensure imports/exports/etc are generated by adding one to the
// minimums/maximums.
config.module_config.config.min_types = 1;
config.module_config.config.max_types += 1;
config.module_config.config.min_imports = 1;
config.module_config.config.max_imports += 1;
config.module_config.config.min_funcs = 1;
config.module_config.config.max_funcs += 1;
config.module_config.config.min_exports = 1;
config.module_config.config.max_exports += 1;
// Use the fuzz input to select an async strategy.
config.enable_async(&mut u)?;
let mut poll_amts = Vec::with_capacity(u.arbitrary_len::<u32>()?);
for _ in 0..poll_amts.capacity() {
poll_amts.push(u.int_in_range(0..=10_000)?);
}
let module = config.module_config.generate(&mut u, None)?;
oracles::call_async(&module.to_bytes(), &config, &poll_amts);
Ok(())
}