Merge pull request #2497 from alexcrichton/fuzz-module-linking

Enable fuzzing the module linking implementation
This commit is contained in:
Nick Fitzgerald
2020-12-11 09:46:03 -08:00
committed by GitHub
22 changed files with 377 additions and 152 deletions

60
Cargo.lock generated
View File

@@ -394,7 +394,7 @@ dependencies = [
"souper-ir", "souper-ir",
"target-lexicon", "target-lexicon",
"thiserror", "thiserror",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -597,7 +597,7 @@ dependencies = [
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
"thiserror", "thiserror",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wat", "wat",
] ]
@@ -1167,7 +1167,7 @@ dependencies = [
"smallvec", "smallvec",
"thiserror", "thiserror",
"typemap", "typemap",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wat", "wat",
] ]
@@ -1411,7 +1411,7 @@ dependencies = [
"peepmatic-test-operator", "peepmatic-test-operator",
"peepmatic-traits", "peepmatic-traits",
"serde", "serde",
"wast 28.0.0", "wast 29.0.0",
"z3", "z3",
] ]
@@ -1439,7 +1439,7 @@ dependencies = [
"peepmatic-traits", "peepmatic-traits",
"rand", "rand",
"serde", "serde",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -1464,7 +1464,7 @@ dependencies = [
"serde", "serde",
"serde_test", "serde_test",
"thiserror", "thiserror",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -1476,7 +1476,7 @@ dependencies = [
"peepmatic", "peepmatic",
"peepmatic-test-operator", "peepmatic-test-operator",
"souper-ir", "souper-ir",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -1497,7 +1497,7 @@ version = "0.68.0"
dependencies = [ dependencies = [
"peepmatic-traits", "peepmatic-traits",
"serde", "serde",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -2356,18 +2356,18 @@ dependencies = [
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.1.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49891b7c581cf9e0090b25cd274e6498ad478f0a7819319ea96da2f253caaacb" checksum = "ed89eaf99e08b84f96e477a16588a07dd3b51dc5f07291c3706782f62a10a5e1"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
[[package]] [[package]]
name = "wasm-smith" name = "wasm-smith"
version = "0.1.12" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fdf8c9ba2fdc0d8ffe3f7e5b23b5aac377eeca817a9885c058f27c8de5c500" checksum = "cdd382e46cf44347f4d0c29122143cbab85cf248b9a8f680845c0239b6842a85"
dependencies = [ dependencies = [
"arbitrary", "arbitrary",
"leb128", "leb128",
@@ -2406,18 +2406,18 @@ checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.69.2" version = "0.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd2dd6dadf3a723971297bcc0ec103e0aa8118bf68e23f49cb575e21621894a8" checksum = "ed1b3f9e9cf01a580b9f3281214dfdb1922b5dfb8494ee312ca03ae10036c2a2"
[[package]] [[package]]
name = "wasmprinter" name = "wasmprinter"
version = "0.2.16" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dba006f5c5bf41a2a5c3b45e861ea6eb067382acb022b6a35a00a0390f9547f6" checksum = "f89b2b24dce17e27fe9c09c28331cbd77067fcde5c6ea2508ac84bcbd5d3e018"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"wasmparser 0.69.2", "wasmparser 0.70.0",
] ]
[[package]] [[package]]
@@ -2438,7 +2438,7 @@ dependencies = [
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",
"tempfile", "tempfile",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmtime-cache", "wasmtime-cache",
"wasmtime-environ", "wasmtime-environ",
"wasmtime-jit", "wasmtime-jit",
@@ -2516,7 +2516,7 @@ dependencies = [
"test-programs", "test-programs",
"tracing-subscriber", "tracing-subscriber",
"wasi-common", "wasi-common",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmtime", "wasmtime",
"wasmtime-cache", "wasmtime-cache",
"wasmtime-debug", "wasmtime-debug",
@@ -2552,7 +2552,7 @@ dependencies = [
"object", "object",
"target-lexicon", "target-lexicon",
"thiserror", "thiserror",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmtime-environ", "wasmtime-environ",
] ]
@@ -2571,7 +2571,7 @@ dependencies = [
"more-asserts", "more-asserts",
"serde", "serde",
"thiserror", "thiserror",
"wasmparser 0.69.2", "wasmparser 0.70.0",
] ]
[[package]] [[package]]
@@ -2600,7 +2600,7 @@ dependencies = [
"rayon", "rayon",
"wasm-smith", "wasm-smith",
"wasmi", "wasmi",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmprinter", "wasmprinter",
"wasmtime", "wasmtime",
"wasmtime-wast", "wasmtime-wast",
@@ -2628,7 +2628,7 @@ dependencies = [
"serde", "serde",
"target-lexicon", "target-lexicon",
"thiserror", "thiserror",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmtime-cranelift", "wasmtime-cranelift",
"wasmtime-debug", "wasmtime-debug",
"wasmtime-environ", "wasmtime-environ",
@@ -2645,7 +2645,7 @@ version = "0.21.0"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"lightbeam", "lightbeam",
"wasmparser 0.69.2", "wasmparser 0.70.0",
"wasmtime-environ", "wasmtime-environ",
] ]
@@ -2752,7 +2752,7 @@ version = "0.21.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"wasmtime", "wasmtime",
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]
@@ -2788,20 +2788,20 @@ dependencies = [
[[package]] [[package]]
name = "wast" name = "wast"
version = "28.0.0" version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c0586061bfacc035034672c8d760802b428ab4c80a92e2a392425c516df9be1" checksum = "dcf2268937131d63c3d833242bf5e075406f9ed868b4265f3280e15dac29ac18"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
[[package]] [[package]]
name = "wat" name = "wat"
version = "1.0.29" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d55b5ec4f9d9396fa99abaafa0688597395e57827dffd89731412ae90c9bf" checksum = "0d11a88d953b298172d218d18f22853f4e6e12873b62755d05617b864d312c68"
dependencies = [ dependencies = [
"wast 28.0.0", "wast 29.0.0",
] ]
[[package]] [[package]]

View File

@@ -38,12 +38,12 @@ anyhow = "1.0.19"
target-lexicon = { version = "0.11.0", default-features = false } target-lexicon = { version = "0.11.0", default-features = false }
pretty_env_logger = "0.4.0" pretty_env_logger = "0.4.0"
file-per-thread-logger = "0.1.1" file-per-thread-logger = "0.1.1"
wat = "1.0.29" wat = "1.0.30"
libc = "0.2.60" libc = "0.2.60"
log = "0.4.8" log = "0.4.8"
rayon = "1.2.1" rayon = "1.2.1"
humantime = "2.0.0" humantime = "2.0.0"
wasmparser = "0.69.2" wasmparser = "0.70.0"
[dev-dependencies] [dev-dependencies]
env_logger = "0.8.1" env_logger = "0.8.1"

View File

@@ -30,7 +30,7 @@ peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, versi
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.68.0" } peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.68.0" }
regalloc = { version = "0.0.31" } regalloc = { version = "0.0.31" }
souper-ir = { version = "2.1.0", optional = true } souper-ir = { version = "2.1.0", optional = true }
wast = { version = "28.0.0", optional = true } wast = { version = "29.0.0", optional = true }
# It is a goal of the cranelift-codegen crate to have minimal external dependencies. # It is a goal of the cranelift-codegen crate to have minimal external dependencies.
# Please don't add any unless they are essential to the task of creating binary # Please don't add any unless they are essential to the task of creating binary
# machine code. Integration tests that need external dependencies can be # machine code. Integration tests that need external dependencies can be

View File

@@ -15,7 +15,7 @@ peepmatic-macro = { version = "0.68.0", path = "crates/macro" }
peepmatic-runtime = { version = "0.68.0", path = "crates/runtime", features = ["construct"] } peepmatic-runtime = { version = "0.68.0", path = "crates/runtime", features = ["construct"] }
peepmatic-traits = { version = "0.68.0", path = "crates/traits" } peepmatic-traits = { version = "0.68.0", path = "crates/traits" }
serde = { version = "1.0.105", features = ["derive"] } serde = { version = "1.0.105", features = ["derive"] }
wast = "28.0.0" wast = "29.0.0"
z3 = { version = "0.7.1", features = ["static-link-z3"] } z3 = { version = "0.7.1", features = ["static-link-z3"] }
[dev-dependencies] [dev-dependencies]

View File

@@ -21,4 +21,4 @@ peepmatic-test-operator = { path = "../test-operator" }
peepmatic-traits = { path = "../traits" } peepmatic-traits = { path = "../traits" }
rand = { version = "0.7.3", features = ["small_rng"] } rand = { version = "0.7.3", features = ["small_rng"] }
serde = "1.0.106" serde = "1.0.106"
wast = "28.0.0" wast = "29.0.0"

View File

@@ -16,7 +16,7 @@ peepmatic-automata = { version = "0.68.0", path = "../automata", features = ["se
peepmatic-traits = { version = "0.68.0", path = "../traits" } peepmatic-traits = { version = "0.68.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] } serde = { version = "1.0.105", features = ["derive"] }
thiserror = "1.0.15" thiserror = "1.0.15"
wast = { version = "28.0.0", optional = true } wast = { version = "29.0.0", optional = true }
[dev-dependencies] [dev-dependencies]
peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" } peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" }

View File

@@ -16,4 +16,4 @@ log = "0.4.8"
[dev-dependencies] [dev-dependencies]
peepmatic = { path = "../..", version = "0.68.0" } peepmatic = { path = "../..", version = "0.68.0" }
peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" } peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" }
wast = "28.0.0" wast = "29.0.0"

View File

@@ -9,4 +9,4 @@ edition = "2018"
[dependencies] [dependencies]
peepmatic-traits = { version = "0.68.0", path = "../traits" } peepmatic-traits = { version = "0.68.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] } serde = { version = "1.0.105", features = ["derive"] }
wast = "28.0.0" wast = "29.0.0"

View File

@@ -12,7 +12,7 @@ keywords = ["webassembly", "wasm"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmparser = { version = "0.69.2", default-features = false } wasmparser = { version = "0.70", default-features = false }
cranelift-codegen = { path = "../codegen", version = "0.68.0", default-features = false } cranelift-codegen = { path = "../codegen", version = "0.68.0", default-features = false }
cranelift-entity = { path = "../entity", version = "0.68.0" } cranelift-entity = { path = "../entity", version = "0.68.0" }
cranelift-frontend = { path = "../frontend", version = "0.68.0", default-features = false } cranelift-frontend = { path = "../frontend", version = "0.68.0", default-features = false }

View File

@@ -538,10 +538,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
} }
/********************************** Exception handing **********************************/ /********************************** Exception handing **********************************/
Operator::Try { .. } Operator::Try { .. }
| Operator::Catch | Operator::Catch { .. }
| Operator::BrOnExn { .. }
| Operator::Throw { .. } | Operator::Throw { .. }
| Operator::Rethrow => { | Operator::Unwind
| Operator::Rethrow { .. } => {
return Err(wasm_unsupported!( return Err(wasm_unsupported!(
"proposed exception handling operator {:?}", "proposed exception handling operator {:?}",
op op

View File

@@ -13,7 +13,7 @@ edition = "2018"
[dependencies] [dependencies]
gimli = "0.23.0" gimli = "0.23.0"
wasmparser = "0.69.2" wasmparser = "0.70"
object = { version = "0.22.0", default-features = false, features = ["read", "write"] } object = { version = "0.22.0", default-features = false, features = ["read", "write"] }
wasmtime-environ = { path = "../environ", version = "0.21.0" } wasmtime-environ = { path = "../environ", version = "0.21.0" }
target-lexicon = { version = "0.11.0", default-features = false } target-lexicon = { version = "0.11.0", default-features = false }

View File

@@ -16,7 +16,7 @@ anyhow = "1.0"
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0", features = ["enable-serde"] } cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0", features = ["enable-serde"] }
cranelift-entity = { path = "../../cranelift/entity", version = "0.68.0", features = ["enable-serde"] } cranelift-entity = { path = "../../cranelift/entity", version = "0.68.0", features = ["enable-serde"] }
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.68.0", features = ["enable-serde"] } cranelift-wasm = { path = "../../cranelift/wasm", version = "0.68.0", features = ["enable-serde"] }
wasmparser = "0.69.2" wasmparser = "0.70"
indexmap = { version = "1.0.2", features = ["serde-1"] } indexmap = { version = "1.0.2", features = ["serde-1"] }
thiserror = "1.0.4" thiserror = "1.0.4"
serde = { version = "1.0.94", features = ["derive"] } serde = { version = "1.0.94", features = ["derive"] }

View File

@@ -12,11 +12,11 @@ arbitrary = { version = "0.4.1", features = ["derive"] }
env_logger = "0.8.1" env_logger = "0.8.1"
log = "0.4.8" log = "0.4.8"
rayon = "1.2.1" rayon = "1.2.1"
wasmparser = "0.69.2" wasmparser = "0.70"
wasmprinter = "0.2.16" wasmprinter = "0.2.17"
wasmtime = { path = "../wasmtime" } wasmtime = { path = "../wasmtime" }
wasmtime-wast = { path = "../wast" } wasmtime-wast = { path = "../wast" }
wasm-smith = "0.1.12" wasm-smith = "0.2.0"
wasmi = "0.7.0" wasmi = "0.7.0"
[dev-dependencies] [dev-dependencies]

View File

@@ -38,6 +38,7 @@ pub fn fuzz_default_config(strategy: wasmtime::Strategy) -> anyhow::Result<wasmt
.cranelift_nan_canonicalization(true) .cranelift_nan_canonicalization(true)
.wasm_bulk_memory(true) .wasm_bulk_memory(true)
.wasm_reference_types(true) .wasm_reference_types(true)
.wasm_module_linking(true)
.strategy(strategy)?; .strategy(strategy)?;
Ok(config) Ok(config)
} }

View File

@@ -91,26 +91,15 @@ pub fn instantiate_with_config(wasm: &[u8], mut config: Config, timeout: Option<
} }
log_wasm(wasm); log_wasm(wasm);
let module = match Module::new(&engine, wasm) { let module = Module::new(&engine, wasm).unwrap();
Ok(module) => module, let imports = dummy_imports(&store, module.imports());
Err(_) => return,
};
let imports = match dummy_imports(&store, module.imports()) { match Instance::new(&store, &module, &imports) {
Ok(imps) => imps, Ok(_) => {}
Err(_) => { // Allow traps which can happen normally with `unreachable`
// There are some value types that we can't synthesize a Err(e) if e.downcast_ref::<Trap>().is_some() => {}
// dummy value for (e.g. externrefs) and for modules that Err(e) => panic!("failed to instantiate {}", e),
// import things of these types we skip instantiation.
return;
} }
};
// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
// table might not have room for an element segment that we want to
// initialize into it.
let _result = Instance::new(&store, &module, &imports);
} }
/// Compile the Wasm buffer, and implicitly fail if we have an unexpected /// Compile the Wasm buffer, and implicitly fail if we have an unexpected
@@ -162,31 +151,14 @@ pub fn differential_execution(
let engine = Engine::new(config); let engine = Engine::new(config);
let store = Store::new(&engine); let store = Store::new(&engine);
let module = match Module::new(&engine, &wasm) { let module = Module::new(&engine, &wasm).unwrap();
Ok(module) => module,
// The module might rely on some feature that our config didn't
// enable or something like that.
Err(e) => {
eprintln!("Warning: failed to compile `wasm-opt -ttf` module: {}", e);
continue;
}
};
// TODO: we should implement tracing versions of these dummy imports // TODO: we should implement tracing versions of these dummy imports
// that record a trace of the order that imported functions were called // that record a trace of the order that imported functions were called
// in and with what values. Like the results of exported functions, // in and with what values. Like the results of exported functions,
// calls to imports should also yield the same values for each // calls to imports should also yield the same values for each
// configuration, and we should assert that. // configuration, and we should assert that.
let imports = match dummy_imports(&store, module.imports()) { let imports = dummy_imports(&store, module.imports());
Ok(imps) => imps,
Err(e) => {
// There are some value types that we can't synthesize a
// dummy value for (e.g. externrefs) and for modules that
// import things of these types we skip instantiation.
eprintln!("Warning: failed to synthesize dummy imports: {}", e);
continue;
}
};
// Don't unwrap this: there can be instantiation-/link-time errors that // Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported // aren't caught during validation or compilation. For example, an imported
@@ -212,10 +184,7 @@ pub fn differential_execution(
init_hang_limit(&instance); init_hang_limit(&instance);
let ty = f.ty(); let ty = f.ty();
let params = match dummy::dummy_values(ty.params()) { let params = dummy::dummy_values(ty.params());
Ok(p) => p,
Err(_) => continue,
};
let this_result = f.call(&params).map_err(|e| e.downcast::<Trap>().unwrap()); let this_result = f.call(&params).map_err(|e| e.downcast::<Trap>().unwrap());
let existing_result = export_func_results let existing_result = export_func_results
@@ -353,16 +322,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
}; };
let store = store.as_ref().unwrap(); let store = store.as_ref().unwrap();
let imports = dummy_imports(store, module.imports());
let imports = match dummy_imports(store, module.imports()) {
Ok(imps) => imps,
Err(_) => {
// There are some value types that we can't synthesize a
// dummy value for (e.g. externrefs) and for modules that
// import things of these types we skip instantiation.
continue;
}
};
// Don't unwrap this: there can be instantiation-/link-time errors that // Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported // aren't caught during validation or compilation. For example, an imported
@@ -408,10 +368,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
let nth = nth % funcs.len(); let nth = nth % funcs.len();
let f = &funcs[nth]; let f = &funcs[nth];
let ty = f.ty(); let ty = f.ty();
let params = match dummy::dummy_values(ty.params()) { let params = dummy::dummy_values(ty.params());
Ok(p) => p,
Err(_) => continue,
};
let _ = f.call(&params); let _ = f.call(&params);
} }
} }
@@ -509,7 +466,7 @@ impl wasm_smith::Config for DifferentialWasmiModuleConfig {
1 1
} }
fn max_memories(&self) -> u32 { fn max_memories(&self) -> usize {
1 1
} }

View File

@@ -1,27 +1,23 @@
//! Dummy implementations of things that a Wasm module can import. //! Dummy implementations of things that a Wasm module can import.
use wasmtime::{ use std::fmt::Write;
Extern, ExternType, Func, FuncType, Global, GlobalType, ImportType, Memory, MemoryType, Store, use wasmtime::*;
Table, TableType, Trap, Val, ValType,
};
/// Create a set of dummy functions/globals/etc for the given imports. /// Create a set of dummy functions/globals/etc for the given imports.
pub fn dummy_imports<'module>( pub fn dummy_imports<'module>(
store: &Store, store: &Store,
import_tys: impl Iterator<Item = ImportType<'module>>, import_tys: impl Iterator<Item = ImportType<'module>>,
) -> Result<Vec<Extern>, Trap> { ) -> Vec<Extern> {
import_tys import_tys
.map(|imp| { .map(|imp| match imp.ty() {
Ok(match imp.ty() {
ExternType::Func(func_ty) => Extern::Func(dummy_func(&store, func_ty)), ExternType::Func(func_ty) => Extern::Func(dummy_func(&store, func_ty)),
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)?), ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)),
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_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) => {
// FIXME(#2094) Extern::Instance(dummy_instance(&store, instance_ty))
ExternType::Instance(_) => unimplemented!(), }
ExternType::Module(_) => unimplemented!(), ExternType::Module(module_ty) => Extern::Module(dummy_module(&store, module_ty)),
})
}) })
.collect() .collect()
} }
@@ -30,55 +26,326 @@ pub fn dummy_imports<'module>(
pub fn dummy_func(store: &Store, ty: FuncType) -> Func { pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
Func::new(store, ty.clone(), move |_, _, results| { Func::new(store, ty.clone(), move |_, _, results| {
for (ret_ty, result) in ty.results().zip(results) { for (ret_ty, result) in ty.results().zip(results) {
*result = dummy_value(ret_ty)?; *result = dummy_value(ret_ty);
} }
Ok(()) Ok(())
}) })
} }
/// Construct a dummy value for the given value type. /// Construct a dummy value for the given value type.
pub fn dummy_value(val_ty: ValType) -> Result<Val, Trap> { pub fn dummy_value(val_ty: ValType) -> Val {
Ok(match val_ty { match val_ty {
ValType::I32 => Val::I32(0), ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0), ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0), ValType::F32 => Val::F32(0),
ValType::F64 => Val::F64(0), ValType::F64 => Val::F64(0),
ValType::V128 => { ValType::V128 => Val::V128(0),
return Err(Trap::new( ValType::ExternRef => Val::ExternRef(None),
"dummy_value: unsupported function return type: v128".to_string(), ValType::FuncRef => Val::FuncRef(None),
))
} }
ValType::ExternRef => {
return Err(Trap::new(
"dummy_value: unsupported function return type: externref".to_string(),
))
}
ValType::FuncRef => {
return Err(Trap::new(
"dummy_value: unsupported function return type: funcref".to_string(),
))
}
})
} }
/// Construct a sequence of dummy values for the given types. /// Construct a sequence of dummy values for the given types.
pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Result<Vec<Val>, Trap> { pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Vec<Val> {
val_tys.into_iter().map(dummy_value).collect() val_tys.into_iter().map(dummy_value).collect()
} }
/// Construct a dummy global for the given global type. /// Construct a dummy global for the given global type.
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> { pub fn dummy_global(store: &Store, ty: GlobalType) -> Global {
let val = dummy_value(ty.content().clone())?; let val = dummy_value(ty.content().clone());
Ok(Global::new(store, ty, val).unwrap()) Global::new(store, ty, val).unwrap()
} }
/// Construct a dummy table for the given table type. /// Construct a dummy table for the given table type.
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> { pub fn dummy_table(store: &Store, ty: TableType) -> Table {
let init_val = dummy_value(ty.element().clone())?; let init_val = dummy_value(ty.element().clone());
Ok(Table::new(store, ty, init_val).unwrap()) Table::new(store, ty, init_val).unwrap()
} }
/// Construct a dummy memory for the given memory type. /// Construct a dummy memory for the given memory type.
pub fn dummy_memory(store: &Store, ty: MemoryType) -> Memory { pub fn dummy_memory(store: &Store, ty: MemoryType) -> Memory {
Memory::new(store, ty) Memory::new(store, ty)
} }
/// Construct a dummy instance for the given instance type.
///
/// This is done by using the expected type to generate a module on-the-fly
/// which we the instantiate.
pub fn dummy_instance(store: &Store, ty: InstanceType) -> Instance {
let mut wat = WatGenerator::new();
for ty in ty.exports() {
wat.export(&ty);
}
let module = Module::new(store.engine(), &wat.finish()).unwrap();
Instance::new(store, &module, &[]).unwrap()
}
/// Construct a dummy module for the given module type.
///
/// This is done by using the expected type to generate a module on-the-fly.
pub fn dummy_module(store: &Store, ty: ModuleType) -> Module {
let mut wat = WatGenerator::new();
for ty in ty.imports() {
wat.import(&ty);
}
for ty in ty.exports() {
wat.export(&ty);
}
Module::new(store.engine(), &wat.finish()).unwrap()
}
struct WatGenerator {
tmp: usize,
dst: String,
}
impl WatGenerator {
fn new() -> WatGenerator {
WatGenerator {
tmp: 0,
dst: String::from("(module\n"),
}
}
fn finish(mut self) -> String {
self.dst.push_str(")\n");
self.dst
}
fn import(&mut self, ty: &ImportType<'_>) {
write!(self.dst, "(import ").unwrap();
self.str(ty.module());
write!(self.dst, " ").unwrap();
if let Some(field) = ty.name() {
self.str(field);
write!(self.dst, " ").unwrap();
}
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
fn item_ty(&mut self, ty: &ExternType) {
match ty {
ExternType::Memory(mem) => {
write!(
self.dst,
"(memory {} {})",
mem.limits().min(),
match mem.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
}
)
.unwrap();
}
ExternType::Table(table) => {
write!(
self.dst,
"(table {} {} {})",
table.limits().min(),
match table.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
},
wat_ty(table.element()),
)
.unwrap();
}
ExternType::Global(ty) => {
if ty.mutability() == Mutability::Const {
write!(self.dst, "(global {})", wat_ty(ty.content())).unwrap();
} else {
write!(self.dst, "(global (mut {}))", wat_ty(ty.content())).unwrap();
}
}
ExternType::Func(ty) => {
write!(self.dst, "(func ").unwrap();
self.func_sig(ty);
write!(self.dst, ")").unwrap();
}
ExternType::Instance(ty) => {
writeln!(self.dst, "(instance").unwrap();
for ty in ty.exports() {
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " ").unwrap();
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
write!(self.dst, ")").unwrap();
}
ExternType::Module(ty) => {
writeln!(self.dst, "(module").unwrap();
for ty in ty.imports() {
self.import(&ty);
writeln!(self.dst, "").unwrap();
}
for ty in ty.exports() {
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " ").unwrap();
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
write!(self.dst, ")").unwrap();
}
}
}
fn export(&mut self, ty: &ExportType<'_>) {
let wat_name = format!("item{}", self.tmp);
self.tmp += 1;
let item_ty = ty.ty();
self.item(&wat_name, &item_ty);
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " (").unwrap();
match item_ty {
ExternType::Memory(_) => write!(self.dst, "memory").unwrap(),
ExternType::Global(_) => write!(self.dst, "global").unwrap(),
ExternType::Func(_) => write!(self.dst, "func").unwrap(),
ExternType::Instance(_) => write!(self.dst, "instance").unwrap(),
ExternType::Table(_) => write!(self.dst, "table").unwrap(),
ExternType::Module(_) => write!(self.dst, "module").unwrap(),
}
writeln!(self.dst, " ${}))", wat_name).unwrap();
}
fn item(&mut self, name: &str, ty: &ExternType) {
match ty {
ExternType::Memory(mem) => {
write!(
self.dst,
"(memory ${} {} {})\n",
name,
mem.limits().min(),
match mem.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
}
)
.unwrap();
}
ExternType::Table(table) => {
write!(
self.dst,
"(table ${} {} {} {})\n",
name,
table.limits().min(),
match table.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
},
wat_ty(table.element()),
)
.unwrap();
}
ExternType::Global(ty) => {
write!(self.dst, "(global ${} ", name).unwrap();
if ty.mutability() == Mutability::Var {
write!(self.dst, "(mut ").unwrap();
}
write!(self.dst, "{}", wat_ty(ty.content())).unwrap();
if ty.mutability() == Mutability::Var {
write!(self.dst, ")").unwrap();
}
write!(self.dst, " (").unwrap();
self.value(ty.content());
writeln!(self.dst, "))").unwrap();
}
ExternType::Func(ty) => {
write!(self.dst, "(func ${} ", name).unwrap();
self.func_sig(ty);
for ty in ty.results() {
writeln!(self.dst, "").unwrap();
self.value(&ty);
}
writeln!(self.dst, ")").unwrap();
}
ExternType::Module(ty) => {
writeln!(self.dst, "(module ${}", name).unwrap();
for ty in ty.imports() {
self.import(&ty);
}
for ty in ty.exports() {
self.export(&ty);
}
self.dst.push_str(")\n");
}
ExternType::Instance(ty) => {
writeln!(self.dst, "(module ${}_module", name).unwrap();
for ty in ty.exports() {
self.export(&ty);
}
self.dst.push_str(")\n");
writeln!(self.dst, "(instance ${} (instantiate ${0}_module))", name).unwrap();
}
}
}
fn func_sig(&mut self, ty: &FuncType) {
write!(self.dst, "(param ").unwrap();
for ty in ty.params() {
write!(self.dst, "{} ", wat_ty(&ty)).unwrap();
}
write!(self.dst, ") (result ").unwrap();
for ty in ty.results() {
write!(self.dst, "{} ", wat_ty(&ty)).unwrap();
}
write!(self.dst, ")").unwrap();
}
fn value(&mut self, ty: &ValType) {
match ty {
ValType::I32 => write!(self.dst, "i32.const 0").unwrap(),
ValType::I64 => write!(self.dst, "i64.const 0").unwrap(),
ValType::F32 => write!(self.dst, "f32.const 0").unwrap(),
ValType::F64 => write!(self.dst, "f64.const 0").unwrap(),
ValType::V128 => write!(self.dst, "v128.const i32x4 0 0 0 0").unwrap(),
ValType::ExternRef => write!(self.dst, "ref.null extern").unwrap(),
ValType::FuncRef => write!(self.dst, "ref.null func").unwrap(),
}
}
fn str(&mut self, name: &str) {
let mut bytes = [0; 4];
self.dst.push_str("\"");
for c in name.chars() {
let v = c as u32;
if v >= 0x20 && v < 0x7f && c != '"' && c != '\\' && v < 0xff {
self.dst.push(c);
} else {
for byte in c.encode_utf8(&mut bytes).as_bytes() {
self.hex_byte(*byte);
}
}
}
self.dst.push_str("\"");
}
fn hex_byte(&mut self, byte: u8) {
fn to_hex(b: u8) -> char {
if b < 10 {
(b'0' + b) as char
} else {
(b'a' + b - 10) as char
}
}
self.dst.push('\\');
self.dst.push(to_hex((byte >> 4) & 0xf));
self.dst.push(to_hex(byte & 0xf));
}
}
fn wat_ty(ty: &ValType) -> &'static str {
match ty {
ValType::I32 => "i32",
ValType::I64 => "i64",
ValType::F32 => "f32",
ValType::F64 => "f64",
ValType::V128 => "v128",
ValType::ExternRef => "externref",
ValType::FuncRef => "funcref",
}
}

View File

@@ -28,7 +28,7 @@ rayon = { version = "1.0", optional = true }
region = "2.1.0" region = "2.1.0"
thiserror = "1.0.4" thiserror = "1.0.4"
target-lexicon = { version = "0.11.0", default-features = false } target-lexicon = { version = "0.11.0", default-features = false }
wasmparser = "0.69.2" wasmparser = "0.70"
more-asserts = "0.2.1" more-asserts = "0.2.1"
anyhow = "1.0" anyhow = "1.0"
cfg-if = "1.0" cfg-if = "1.0"

View File

@@ -24,7 +24,7 @@ more-asserts = "0.2.1"
smallvec = "1.0.0" smallvec = "1.0.0"
thiserror = "1.0.9" thiserror = "1.0.9"
typemap = "0.3" typemap = "0.3"
wasmparser = "0.69.2" wasmparser = "0.70"
[dev-dependencies] [dev-dependencies]
lazy_static = "1.2" lazy_static = "1.2"

View File

@@ -13,6 +13,6 @@ edition = "2018"
[dependencies] [dependencies]
lightbeam = { path = "..", version = "0.21.0" } lightbeam = { path = "..", version = "0.21.0" }
wasmparser = "0.69.2" wasmparser = "0.70"
cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.68.0" } cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.68.0" }
wasmtime-environ = { path = "../../environ", version = "0.21.0" } wasmtime-environ = { path = "../../environ", version = "0.21.0" }

View File

@@ -16,7 +16,7 @@ wasmtime-jit = { path = "../jit", version = "0.21.0" }
wasmtime-cache = { path = "../cache", version = "0.21.0", optional = true } wasmtime-cache = { path = "../cache", version = "0.21.0", optional = true }
wasmtime-profiling = { path = "../profiling", version = "0.21.0" } wasmtime-profiling = { path = "../profiling", version = "0.21.0" }
target-lexicon = { version = "0.11.0", default-features = false } target-lexicon = { version = "0.11.0", default-features = false }
wasmparser = "0.69.2" wasmparser = "0.70"
anyhow = "1.0.19" anyhow = "1.0.19"
region = "2.2.0" region = "2.2.0"
libc = "0.2" libc = "0.2"

View File

@@ -13,7 +13,7 @@ edition = "2018"
[dependencies] [dependencies]
anyhow = "1.0.19" anyhow = "1.0.19"
wasmtime = { path = "../wasmtime", version = "0.21.0", default-features = false } wasmtime = { path = "../wasmtime", version = "0.21.0", default-features = false }
wast = "28.0.0" wast = "29.0.0"
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }

View File

@@ -17,7 +17,7 @@ target-lexicon = "0.11"
peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true } peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true }
wasmtime = { path = "../crates/wasmtime" } wasmtime = { path = "../crates/wasmtime" }
wasmtime-fuzzing = { path = "../crates/fuzzing" } wasmtime-fuzzing = { path = "../crates/fuzzing" }
wasm-smith = "0.1.12" wasm-smith = "0.2.0"
[features] [features]
experimental_x64 = ["wasmtime-fuzzing/experimental_x64"] experimental_x64 = ["wasmtime-fuzzing/experimental_x64"]