diff --git a/Cargo.lock b/Cargo.lock index debe8fbd6a..018e1a438c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,15 +41,9 @@ checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" [[package]] name = "arbitrary" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" - -[[package]] -name = "arbitrary" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491d5e42b1a073ff1fc1e0a02744b3f8bee9cf4bfd552053cac36c64b879795d" +checksum = "16971f2f0ce65c5cf2a1546cc6a0af102ecb11e265ddaa9433fb3e5bfdf676a4" dependencies = [ "derive_arbitrary", ] @@ -521,9 +515,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab2f0544254a47cabc58956cc7ebda74c3b796bb2761e3fe8f29fdde632ad95" +checksum = "caedd6a71b6d00bdc458ec8ffbfd12689c1ee7ffa69ad9933310aaf2f08f18d8" dependencies = [ "proc-macro2", "syn", @@ -955,11 +949,11 @@ checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" [[package]] name = "libfuzzer-sys" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e969cd2be7a2aae0acbbe205da49134148db2287fb45a811bf441ed72f09a35" +checksum = "fb789afcc589a08928d1e466087445ab740a0f70a2ee23d9349a0e3723d65e1b" dependencies = [ - "arbitrary 0.3.3", + "arbitrary", "cc", ] @@ -2121,7 +2115,6 @@ dependencies = [ name = "wasmtime-fuzz" version = "0.12.0" dependencies = [ - "arbitrary 0.2.0", "cranelift-codegen", "cranelift-reader", "cranelift-wasm", @@ -2136,7 +2129,7 @@ name = "wasmtime-fuzzing" version = "0.12.0" dependencies = [ "anyhow", - "arbitrary 0.3.3", + "arbitrary", "binaryen", "env_logger 0.7.1", "log", diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 74eec7c213..835b76edfc 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -8,7 +8,7 @@ version = "0.12.0" [dependencies] anyhow = "1.0.22" -arbitrary = { version = "0.3.2", features = ["derive"] } +arbitrary = { version = "0.4.0", features = ["derive"] } binaryen = "0.10.0" env_logger = "0.7.1" log = "0.4.8" diff --git a/crates/fuzzing/src/generators.rs b/crates/fuzzing/src/generators.rs index c3813a1b6e..f982b42844 100644 --- a/crates/fuzzing/src/generators.rs +++ b/crates/fuzzing/src/generators.rs @@ -44,6 +44,10 @@ impl Arbitrary for WasmOptTtf { let wasm = module.write(); Ok(WasmOptTtf { wasm }) } + + fn size_hint(depth: usize) -> (usize, Option) { + as Arbitrary>::size_hint(depth) + } } /// A description of configuration options that we should do differential diff --git a/crates/fuzzing/src/generators/api.rs b/crates/fuzzing/src/generators/api.rs index 9ffe8c5e26..3def5aa9a2 100644 --- a/crates/fuzzing/src/generators/api.rs +++ b/crates/fuzzing/src/generators/api.rs @@ -48,12 +48,20 @@ use ApiCall::*; #[derive(Default)] struct Scope { id_counter: usize, - predicted_rss: usize, + /// Map from a module id to the predicted amount of rss it will take to /// instantiate. modules: BTreeMap, + /// Map from an instance id to the amount of rss it's expected to be using. instances: BTreeMap, + + /// The rough predicted maximum RSS of executing all of our generated API + /// calls thus far. + predicted_rss: usize, + + /// The number of calls of an exported function from an instance. + num_export_calls: usize, } impl Scope { @@ -83,6 +91,11 @@ impl Arbitrary for ApiCalls { let mut scope = Scope::default(); let max_rss = 1 << 30; // 1GB + // Calling an exported function of a `wasm-opt -ttf` module tends to + // take about 20ms. Limit their number to 100, or ~2s, so that we don't + // get too close to our 3s timeout. + let max_export_calls = 100; + for _ in 0..input.arbitrary_len::()? { let mut choices: Vec arbitrary::Result> = vec![]; @@ -122,8 +135,12 @@ impl Arbitrary for ApiCalls { Ok(InstanceDrop { id }) }); } - if swarm.call_exported_func && !scope.instances.is_empty() { + if swarm.call_exported_func + && scope.num_export_calls < max_export_calls + && !scope.instances.is_empty() + { choices.push(|input, scope| { + scope.num_export_calls += 1; let instances: Vec<_> = scope.instances.keys().collect(); let instance = **input.choose(&instances)?; let nth = usize::arbitrary(input)?; @@ -140,6 +157,25 @@ impl Arbitrary for ApiCalls { Ok(ApiCalls { calls }) } + + fn size_hint(depth: usize) -> (usize, Option) { + arbitrary::size_hint::recursion_guard(depth, |depth| { + arbitrary::size_hint::or( + // This is the stuff we unconditionally need, which affects the + // minimum size. + arbitrary::size_hint::and( + ::size_hint(depth), + // `arbitrary_config` uses two bools when + // `swarm.config_debug_info` is true. + <(bool, bool) as Arbitrary>::size_hint(depth), + ), + // We can generate arbitrary `WasmOptTtf` instances, which have + // no upper bound on the number of bytes they consume. This sets + // the upper bound to `None`. + ::size_hint(depth), + ) + }) + } } fn arbitrary_config( diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 6a24baa0d8..2c9eb4dc56 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -9,11 +9,10 @@ publish = false cargo-fuzz = true [dependencies] -arbitrary = "0.2.0" cranelift-codegen = { path = "../cranelift/codegen" } cranelift-reader = { path = "../cranelift/reader" } cranelift-wasm = { path = "../cranelift/wasm" } -libfuzzer-sys = "0.2.1" +libfuzzer-sys = "0.3.1" target-lexicon = "0.10" wasmtime = { path = "../crates/api" } wasmtime-fuzzing = { path = "../crates/fuzzing" }