Skip to content

Commit

Permalink
Fix fuzzers requesting 4gb memories (#3029)
Browse files Browse the repository at this point in the history
Wasmtime was updated to reject creation of memories exactly 4gb in size
in #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 authored Jun 24, 2021
1 parent ab53612 commit 1047c4e
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 1047c4e

Please sign in to comment.