diff --git a/Cargo.lock b/Cargo.lock index 38a575a17c..2a5133dfc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1135,6 +1135,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "ff" version = "0.10.1" @@ -2373,9 +2382,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -2816,13 +2825,13 @@ checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.3", "redox_syscall", "remove_dir_all", "winapi", @@ -3584,6 +3593,7 @@ dependencies = [ "env_logger 0.8.3", "log", "rayon", + "tempfile", "v8", "wasm-encoder", "wasm-smith", diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 78fbe055c4..6c89ab9962 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -13,6 +13,7 @@ arbitrary = { version = "1.0.0", features = ["derive"] } env_logger = "0.8.1" log = "0.4.8" rayon = "1.2.1" +tempfile = "3.3.0" wasmparser = "0.82" wasmprinter = "0.2.32" wasmtime = { path = "../wasmtime" } diff --git a/crates/fuzzing/src/generators.rs b/crates/fuzzing/src/generators.rs index 157d0335b3..e91d3f3f97 100644 --- a/crates/fuzzing/src/generators.rs +++ b/crates/fuzzing/src/generators.rs @@ -17,7 +17,7 @@ use arbitrary::{Arbitrary, Unstructured}; use std::sync::Arc; use std::time::Duration; use wasm_smith::SwarmConfig; -use wasmtime::{Engine, LinearMemory, MemoryCreator, MemoryType, Store}; +use wasmtime::{Engine, LinearMemory, MemoryCreator, MemoryType, Module, Store}; #[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)] enum OptLevel { @@ -62,6 +62,7 @@ pub struct WasmtimeConfig { memory_config: MemoryConfig, force_jump_veneers: bool, memfd: bool, + use_precompiled_cwasm: bool, } #[derive(Arbitrary, Clone, Debug, Eq, Hash, PartialEq)] @@ -170,6 +171,26 @@ impl Config { Ok(Timeout::Fuel(100_000)) } } + + /// Compiles the `wasm` within the `engine` provided. + /// + /// This notably will use `Module::{serialize,deserialize_file}` to + /// round-trip if configured in the fuzzer. + pub fn compile(&self, engine: &Engine, wasm: &[u8]) -> Result { + // Propagate this error in case the caller wants to handle + // valid-vs-invalid wasm. + let module = Module::new(engine, wasm)?; + if !self.wasmtime.use_precompiled_cwasm { + return Ok(module); + } + + // Don't propagate these errors to prevent them from accidentally being + // interpreted as invalid wasm, these should never fail on a + // well-behaved host system. + let file = tempfile::NamedTempFile::new().unwrap(); + std::fs::write(file.path(), module.serialize().unwrap()).unwrap(); + unsafe { Ok(Module::deserialize_file(engine, file.path()).unwrap()) } + } } struct UnalignedMemoryCreator; diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index b351516d95..9d5a647d9f 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -143,7 +143,7 @@ pub fn instantiate(wasm: &[u8], known_valid: bool, config: &generators::Config, } log_wasm(wasm); - let module = match Module::new(store.engine(), wasm) { + let module = match config.compile(store.engine(), wasm) { Ok(module) => module, Err(_) if !known_valid => return, Err(e) => panic!("failed to compile module: {:?}", e), @@ -222,7 +222,7 @@ pub fn differential_execution( log::debug!("fuzz config: {:?}", fuzz_config); let mut store = fuzz_config.to_store(); - let module = Module::new(store.engine(), &wasm).unwrap(); + let module = fuzz_config.compile(store.engine(), &wasm).unwrap(); // TODO: we should implement tracing versions of these dummy imports // that record a trace of the order that imported functions were called @@ -432,7 +432,7 @@ pub fn table_ops(mut fuzz_config: generators::Config, ops: generators::table_ops let wasm = ops.to_wasm_binary(); log_wasm(&wasm); - let module = match Module::new(store.engine(), &wasm) { + let module = match fuzz_config.compile(store.engine(), &wasm) { Ok(m) => m, Err(_) => return, }; @@ -736,7 +736,9 @@ fn differential_store( fuzz_config: &generators::Config, ) -> (Module, Store) { let store = fuzz_config.to_store(); - let module = Module::new(store.engine(), &wasm).expect("Wasmtime can compile module"); + let module = fuzz_config + .compile(store.engine(), wasm) + .expect("Wasmtime can compile module"); (module, store) }