Improve stability for fuzz targets. (#3804)
This commit improves the stability of the fuzz targets by ensuring the generated configs and modules are congruent, especially when the pooling allocator is being used. For the `differential` target, this means both configurations must use the same allocation strategy for now as one side generates the module that might not be compatible with another arbitrary config now that we fuzz the pooling allocator. These changes also ensure that constraints put on the config are more consistently applied, especially when using a fuel-based timeout.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
use libfuzzer_sys::arbitrary::{Result, Unstructured};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use wasmtime_fuzzing::generators::InstanceAllocationStrategy;
|
||||
use wasmtime_fuzzing::{generators, oracles};
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
@@ -13,12 +14,28 @@ fuzz_target!(|data: &[u8]| {
|
||||
fn run(data: &[u8]) -> Result<()> {
|
||||
let mut u = Unstructured::new(data);
|
||||
|
||||
let lhs: generators::WasmtimeConfig = u.arbitrary()?;
|
||||
let rhs: generators::WasmtimeConfig = u.arbitrary()?;
|
||||
let config: generators::ModuleConfig = u.arbitrary()?;
|
||||
let mut module = config.generate(&mut u)?;
|
||||
module.ensure_termination(1000);
|
||||
let mut config: generators::Config = u.arbitrary()?;
|
||||
let module = config.generate(&mut u, Some(1000))?;
|
||||
|
||||
oracles::differential_execution(&module.to_bytes(), &config, &[lhs, rhs]);
|
||||
let lhs = config.wasmtime;
|
||||
let mut rhs: generators::WasmtimeConfig = u.arbitrary()?;
|
||||
|
||||
// Use the same allocation strategy between the two configs.
|
||||
//
|
||||
// Ideally this wouldn't be necessary, but if the lhs is using ondemand
|
||||
// and the rhs is using the pooling allocator (or vice versa), then
|
||||
// the module may have been generated in such a way that is incompatible
|
||||
// with the other allocation strategy.
|
||||
//
|
||||
// We can remove this in the future when it's possible to access the
|
||||
// fields of `wasm_smith::Module` to constrain the pooling allocator
|
||||
// based on what was actually generated.
|
||||
rhs.strategy = lhs.strategy.clone();
|
||||
if let InstanceAllocationStrategy::Pooling { .. } = &rhs.strategy {
|
||||
// Also use the same memory configuration when using the pooling allocator
|
||||
rhs.memory_config = lhs.memory_config.clone();
|
||||
}
|
||||
|
||||
oracles::differential_execution(&module.to_bytes(), &config.module_config, &[lhs, rhs]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -13,15 +13,14 @@ fuzz_target!(|data: &[u8]| {
|
||||
fn run(data: &[u8]) -> Result<()> {
|
||||
let mut u = Unstructured::new(data);
|
||||
let mut config: generators::Config = u.arbitrary()?;
|
||||
config.module_config.set_differential_config();
|
||||
config.set_differential_config();
|
||||
|
||||
// Enable features that v8 has implemented
|
||||
config.module_config.config.simd_enabled = true;
|
||||
config.module_config.config.bulk_memory_enabled = true;
|
||||
config.module_config.config.reference_types_enabled = true;
|
||||
|
||||
let mut module = config.module_config.generate(&mut u)?;
|
||||
module.ensure_termination(1000);
|
||||
let module = config.generate(&mut u, Some(1000))?;
|
||||
oracles::differential_v8_execution(&module.to_bytes(), &config);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -13,9 +13,8 @@ fuzz_target!(|data: &[u8]| {
|
||||
fn run(data: &[u8]) -> Result<()> {
|
||||
let mut u = Unstructured::new(data);
|
||||
let mut config: generators::Config = u.arbitrary()?;
|
||||
config.module_config.set_differential_config();
|
||||
let mut module = config.module_config.generate(&mut u)?;
|
||||
module.ensure_termination(1000);
|
||||
config.set_differential_config();
|
||||
let module = config.generate(&mut u, Some(1000))?;
|
||||
oracles::differential_wasmi_execution(&module.to_bytes(), &config);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ fn run(data: &[u8]) -> Result<()> {
|
||||
|
||||
// Create the modules to instantiate
|
||||
let modules = (0..u.int_in_range(1..=MAX_MODULES)?)
|
||||
.map(|_| Ok(config.module_config.generate(&mut u)?.to_bytes()))
|
||||
.map(|_| Ok(config.generate(&mut u, None)?.to_bytes()))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let max_instances = match &config.wasmtime.strategy {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use libfuzzer_sys::arbitrary::{Result, Unstructured};
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use wasmtime_fuzzing::generators::InstanceAllocationStrategy;
|
||||
use wasmtime_fuzzing::oracles::Timeout;
|
||||
use wasmtime_fuzzing::{generators, oracles};
|
||||
|
||||
@@ -28,21 +27,15 @@ fn run(data: &[u8]) -> Result<()> {
|
||||
// Enable module linking for this fuzz target specifically
|
||||
config.module_config.config.module_linking_enabled = u.arbitrary()?;
|
||||
|
||||
// When using the pooling allocator without a timeout, we must
|
||||
// allow at least 1 more global because the `ensure_termination` call below
|
||||
// will define one.
|
||||
if let Timeout::None = timeout {
|
||||
if let InstanceAllocationStrategy::Pooling { module_limits, .. } =
|
||||
&mut config.wasmtime.strategy
|
||||
{
|
||||
module_limits.globals += 1;
|
||||
}
|
||||
}
|
||||
let module = config.generate(
|
||||
&mut u,
|
||||
if let Timeout::None = timeout {
|
||||
Some(1000)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut module = config.module_config.generate(&mut u)?;
|
||||
if let Timeout::None = timeout {
|
||||
module.ensure_termination(1000);
|
||||
}
|
||||
oracles::instantiate(&module.to_bytes(), true, &config, timeout);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user