Update differential fuzzing configuration (#4386)
* Update differential fuzzing configuration This uses some new features of `wasm-smith` and additionally tweaks the existing fuzz configuration: * More than one function is now allowed to be generated. There's no particular reason to limit differential execution to just one and we may want to explore other interesting module shapes. * More than one function type is now allowed to possibly allow more interesting `block` types. * Memories are now allowed to grow beyond one page, but still say small by staying underneath 10 pages. * Tables are now always limited in their growth to ensure consistent behavior across engines (e.g. with the pooling allocator vs v8). * The `export_everything` feature is used instead of specifying a min/max number of exports. The `wasmi` differential fuzzer was updated to still work if memory is exported, but otherwise the v8 differential fuzzer already worked if a function was exported but a memory wasn't. Both fuzzers continue to execute only the first exported function. Also notable from this update is that the `SwarmConfig` from `wasm-smith` will now include an arbitrary `allowed_instructions` configuration which may help explore the space of interesting modules more effectively. * Fix typos
This commit is contained in:
@@ -272,29 +272,38 @@ impl Config {
|
||||
let config = &mut self.module_config.config;
|
||||
|
||||
config.allow_start_export = false;
|
||||
|
||||
// Make sure there's a type available for the function.
|
||||
config.min_types = 1;
|
||||
config.max_types = 1;
|
||||
config.max_types = config.max_types.max(1);
|
||||
|
||||
// Generate one and only one function
|
||||
// Generate at least one function
|
||||
config.min_funcs = 1;
|
||||
config.max_funcs = 1;
|
||||
config.max_funcs = config.max_funcs.max(1);
|
||||
|
||||
// Give the function a memory, but keep it small
|
||||
config.min_memories = 1;
|
||||
// Allow a memory to be generated, but don't let it get too large.
|
||||
// Additionally require the maximum size to guarantee that the growth
|
||||
// behavior is consistent across engines.
|
||||
config.max_memories = 1;
|
||||
config.max_memory_pages = 1;
|
||||
config.max_memory_pages = 10;
|
||||
config.memory_max_size_required = true;
|
||||
|
||||
// While reference types are disabled below, only allow one table
|
||||
// If tables are generated make sure they don't get too large to avoid
|
||||
// hitting any engine-specific limit. Additionally ensure that the
|
||||
// maximum size is required to guarantee consistent growth across
|
||||
// engines.
|
||||
//
|
||||
// Note that while reference types are disabled below, only allow one
|
||||
// table.
|
||||
config.max_tables = 1;
|
||||
config.max_table_elements = 1_000;
|
||||
config.table_max_size_required = true;
|
||||
|
||||
// Don't allow any imports
|
||||
config.max_imports = 0;
|
||||
|
||||
// Try to get the function and the memory exported
|
||||
config.min_exports = 2;
|
||||
config.max_exports = 4;
|
||||
config.export_everything = true;
|
||||
|
||||
// NaN is canonicalized at the wasm level for differential fuzzing so we
|
||||
// can paper over NaN differences between engines.
|
||||
@@ -317,9 +326,10 @@ impl Config {
|
||||
{
|
||||
// One single-page memory
|
||||
limits.memories = 1;
|
||||
limits.memory_pages = 1;
|
||||
limits.memory_pages = 10;
|
||||
|
||||
limits.tables = 1;
|
||||
limits.table_elements = 1_000;
|
||||
|
||||
match &mut self.wasmtime.memory_config {
|
||||
MemoryConfig::Normal(config) => {
|
||||
|
||||
@@ -718,17 +718,11 @@ pub fn differential_wasmi_execution(wasm: &[u8], config: &generators::Config) ->
|
||||
// Introspect wasmtime module to find name of an exported function and of an
|
||||
// exported memory.
|
||||
let (func_name, ty) = first_exported_function(&wasmtime_module)?;
|
||||
let memory_name = first_exported_memory(&wasmtime_module)?;
|
||||
|
||||
let wasmi_mem_export = wasmi_instance.export_by_name(memory_name).unwrap();
|
||||
let wasmi_mem = wasmi_mem_export.as_memory().unwrap();
|
||||
let wasmi_main_export = wasmi_instance.export_by_name(func_name).unwrap();
|
||||
let wasmi_main = wasmi_main_export.as_func().unwrap();
|
||||
let wasmi_val = wasmi::FuncInstance::invoke(&wasmi_main, &[], &mut wasmi::NopExternals);
|
||||
|
||||
let wasmtime_mem = wasmtime_instance
|
||||
.get_memory(&mut wasmtime_store, memory_name)
|
||||
.expect("memory export is present");
|
||||
let wasmtime_main = wasmtime_instance
|
||||
.get_func(&mut wasmtime_store, func_name)
|
||||
.expect("function export is present");
|
||||
@@ -759,6 +753,17 @@ pub fn differential_wasmi_execution(wasm: &[u8], config: &generators::Config) ->
|
||||
}
|
||||
}
|
||||
|
||||
// Compare linear memories if there's an exported linear memory
|
||||
let memory_name = match first_exported_memory(&wasmtime_module) {
|
||||
Some(name) => name,
|
||||
None => return Some(()),
|
||||
};
|
||||
let wasmi_mem_export = wasmi_instance.export_by_name(memory_name).unwrap();
|
||||
let wasmi_mem = wasmi_mem_export.as_memory().unwrap();
|
||||
let wasmtime_mem = wasmtime_instance
|
||||
.get_memory(&mut wasmtime_store, memory_name)
|
||||
.expect("memory export is present");
|
||||
|
||||
if wasmi_mem.current_size().0 != wasmtime_mem.size(&wasmtime_store) as usize {
|
||||
panic!("resulting memories are not the same size");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user