Skip to content

Commit

Permalink
Fix fuzzers requesting 4gb memories
Browse files Browse the repository at this point in the history
Wasmtime was updated to reject creation of memories exactly 4gb in size
in bytecodealliance#3013, but the fuzzers still had the assumption that any request to
create a host object for a particular wasm type would succeed.
Unfortunately now, though, a request to create a 4gb memory fails. This
is an expected failure, though, so the fix here was to catch the error
and allow it.
  • Loading branch information
alexcrichton committed Jun 24, 2021
1 parent 8172620 commit cc3af6a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 15 deletions.
32 changes: 29 additions & 3 deletions crates/fuzzing/src/oracles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,24 @@ pub fn instantiate_with_config(
Err(_) if !known_valid => return,
Err(e) => panic!("failed to compile module: {:?}", e),
};
let linker = dummy_linker(&mut store, &module);
let linker = match dummy_linker(&mut store, &module) {
Ok(linker) => linker,
Err(e) => {
eprintln!("Warning: failed to create host imports: {:?}", e);

// Currently the only error we want to allow here is ones where we
// ran out of resources creating imports. For example memory
// creation may not succeed if the host is running low on resources.
//
// Other errors, however, are bugs in creation of the host resource.
let string = e.to_string();
assert!(
string.contains("Insufficient resources")
&& string.contains("exceeds memory limits")
);
return;
}
};

match linker.instantiate(&mut store, &module) {
Ok(_) => {}
Expand Down Expand Up @@ -227,7 +244,13 @@ pub fn differential_execution(
// in and with what values. Like the results of exported functions,
// calls to imports should also yield the same values for each
// configuration, and we should assert that.
let linker = dummy_linker(&mut store, &module);
let linker = match dummy_linker(&mut store, &module) {
Ok(linker) => linker,
Err(e) => {
eprintln!("Warning: failed to create host imports: {:?}", e);
continue;
}
};

// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
Expand Down Expand Up @@ -397,7 +420,10 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
};

let store = store.as_mut().unwrap();
let linker = dummy_linker(store, module);
let linker = match dummy_linker(store, module) {
Ok(linker) => linker,
Err(_) => continue,
};

// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
Expand Down
25 changes: 13 additions & 12 deletions crates/fuzzing/src/oracles/dummy.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
//! Dummy implementations of things that a Wasm module can import.
use anyhow::Result;
use std::fmt::Write;
use wasmtime::*;

/// Create a set of dummy functions/globals/etc for the given imports.
pub fn dummy_linker<'module, T>(store: &mut Store<T>, module: &Module) -> Linker<T> {
pub fn dummy_linker<'module, T>(store: &mut Store<T>, module: &Module) -> Result<Linker<T>> {
let mut linker = Linker::new(store.engine());
linker.allow_shadowing(true);
for import in module.imports() {
match import.name() {
Some(name) => {
linker
.define(import.module(), name, dummy_extern(store, import.ty()))
.define(import.module(), name, dummy_extern(store, import.ty())?)
.unwrap();
}
None => match import.ty() {
ExternType::Instance(ty) => {
for ty in ty.exports() {
linker
.define(import.module(), ty.name(), dummy_extern(store, ty.ty()))
.define(import.module(), ty.name(), dummy_extern(store, ty.ty())?)
.unwrap();
}
}
other => {
linker
.define_name(import.module(), dummy_extern(store, other))
.define_name(import.module(), dummy_extern(store, other)?)
.unwrap();
}
},
}
}
linker
Ok(linker)
}

/// Construct a dummy `Extern` from its type signature
pub fn dummy_extern<T>(store: &mut Store<T>, ty: ExternType) -> Extern {
match ty {
pub fn dummy_extern<T>(store: &mut Store<T>, ty: ExternType) -> Result<Extern> {
Ok(match ty {
ExternType::Func(func_ty) => Extern::Func(dummy_func(store, func_ty)),
ExternType::Global(global_ty) => Extern::Global(dummy_global(store, global_ty)),
ExternType::Table(table_ty) => Extern::Table(dummy_table(store, table_ty)),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(store, mem_ty)),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(store, mem_ty)?),
ExternType::Instance(instance_ty) => Extern::Instance(dummy_instance(store, instance_ty)),
ExternType::Module(module_ty) => Extern::Module(dummy_module(store.engine(), module_ty)),
}
})
}

/// Construct a dummy function for the given function type
Expand Down Expand Up @@ -86,8 +87,8 @@ pub fn dummy_table<T>(store: &mut Store<T>, ty: TableType) -> Table {
}

/// Construct a dummy memory for the given memory type.
pub fn dummy_memory<T>(store: &mut Store<T>, ty: MemoryType) -> Memory {
Memory::new(store, ty).unwrap()
pub fn dummy_memory<T>(store: &mut Store<T>, ty: MemoryType) -> Result<Memory> {
Memory::new(store, ty)
}

/// Construct a dummy instance for the given instance type.
Expand Down Expand Up @@ -414,7 +415,7 @@ mod tests {
#[test]
fn dummy_memory_import() {
let mut store = store();
let memory = dummy_memory(&mut store, MemoryType::new(Limits::at_least(1)));
let memory = dummy_memory(&mut store, MemoryType::new(Limits::at_least(1))).unwrap();
assert_eq!(memory.size(&store), 1);
}

Expand Down

0 comments on commit cc3af6a

Please sign in to comment.