Merge pull request #1193 from fitzgen/limit-rayon-to-one-thread-during-fuzzing

Limit rayon to one thread during fuzzing
This commit is contained in:
Nick Fitzgerald
2020-02-28 21:42:53 -08:00
committed by GitHub
6 changed files with 40 additions and 3 deletions

1
Cargo.lock generated
View File

@@ -2366,6 +2366,7 @@ dependencies = [
"binaryen", "binaryen",
"env_logger 0.7.1", "env_logger 0.7.1",
"log", "log",
"rayon",
"wasmparser 0.51.2", "wasmparser 0.51.2",
"wasmprinter", "wasmprinter",
"wasmtime", "wasmtime",

View File

@@ -12,6 +12,7 @@ arbitrary = { version = "0.4.0", features = ["derive"] }
binaryen = "0.10.0" binaryen = "0.10.0"
env_logger = "0.7.1" env_logger = "0.7.1"
log = "0.4.8" log = "0.4.8"
rayon = "1.2.1"
wasmparser = "0.51.2" wasmparser = "0.51.2"
wasmprinter = "0.2.1" wasmprinter = "0.2.1"
wasmtime = { path = "../api", version = "0.12.0" } wasmtime = { path = "../api", version = "0.12.0" }

View File

@@ -32,6 +32,7 @@ impl fmt::Debug for WasmOptTtf {
impl Arbitrary for WasmOptTtf { impl Arbitrary for WasmOptTtf {
fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> { fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> {
crate::init_fuzzing();
let seed: Vec<u8> = Arbitrary::arbitrary(input)?; let seed: Vec<u8> = Arbitrary::arbitrary(input)?;
let module = binaryen::tools::translate_to_fuzz_mvp(&seed); let module = binaryen::tools::translate_to_fuzz_mvp(&seed);
let wasm = module.write(); let wasm = module.write();
@@ -39,6 +40,7 @@ impl Arbitrary for WasmOptTtf {
} }
fn arbitrary_take_rest(input: Unstructured) -> arbitrary::Result<Self> { fn arbitrary_take_rest(input: Unstructured) -> arbitrary::Result<Self> {
crate::init_fuzzing();
let seed: Vec<u8> = Arbitrary::arbitrary_take_rest(input)?; let seed: Vec<u8> = Arbitrary::arbitrary_take_rest(input)?;
let module = binaryen::tools::translate_to_fuzz_mvp(&seed); let module = binaryen::tools::translate_to_fuzz_mvp(&seed);
let wasm = module.write(); let wasm = module.write();

View File

@@ -81,6 +81,8 @@ pub struct ApiCalls {
impl Arbitrary for ApiCalls { impl Arbitrary for ApiCalls {
fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> { fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> {
crate::init_fuzzing();
let swarm = Swarm::arbitrary(input)?; let swarm = Swarm::arbitrary(input)?;
let mut calls = vec![]; let mut calls = vec![];

View File

@@ -4,3 +4,29 @@
pub mod generators; pub mod generators;
pub mod oracles; pub mod oracles;
/// One time start up initialization for fuzzing:
///
/// * Enables `env_logger`.
///
/// * Restricts `rayon` to a single thread in its thread pool, for more
/// deterministic executions.
///
/// If a fuzz target is taking raw input bytes from the fuzzer, it is fine to
/// call this function in the fuzz target's oracle or in the fuzz target
/// itself. However, if the fuzz target takes an `Arbitrary` type, and the
/// `Arbitrary` implementation is not derived and does interesting things, then
/// the `Arbitrary` implementation should call this function, since it runs
/// before the fuzz target itself.
pub(crate) fn init_fuzzing() {
static INIT: std::sync::Once = std::sync::Once::new();
INIT.call_once(|| {
let _ = env_logger::try_init();
rayon::ThreadPoolBuilder::new()
.num_threads(1)
.build_global()
.expect("should only initialize the rayon thread pool once!");
})
}

View File

@@ -18,7 +18,7 @@ use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use wasmtime::*; use wasmtime::*;
fn fuzz_default_config(strategy: Strategy) -> Config { fn fuzz_default_config(strategy: Strategy) -> Config {
drop(env_logger::try_init()); crate::init_fuzzing();
let mut config = Config::new(); let mut config = Config::new();
config config
.cranelift_debug_verifier(true) .cranelift_debug_verifier(true)
@@ -61,6 +61,8 @@ pub fn instantiate(wasm: &[u8], strategy: Strategy) {
/// ///
/// See also `instantiate` functions. /// See also `instantiate` functions.
pub fn instantiate_with_config(wasm: &[u8], config: Config) { pub fn instantiate_with_config(wasm: &[u8], config: Config) {
crate::init_fuzzing();
let engine = Engine::new(&config); let engine = Engine::new(&config);
let store = Store::new(&engine); let store = Store::new(&engine);
@@ -94,6 +96,8 @@ pub fn instantiate_with_config(wasm: &[u8], config: Config) {
/// ///
/// You can control which compiler is used via passing a `Strategy`. /// You can control which compiler is used via passing a `Strategy`.
pub fn compile(wasm: &[u8], strategy: Strategy) { pub fn compile(wasm: &[u8], strategy: Strategy) {
crate::init_fuzzing();
let engine = Engine::new(&fuzz_default_config(strategy)); let engine = Engine::new(&fuzz_default_config(strategy));
let store = Store::new(&engine); let store = Store::new(&engine);
log_wasm(wasm); log_wasm(wasm);
@@ -108,7 +112,8 @@ pub fn differential_execution(
ttf: &crate::generators::WasmOptTtf, ttf: &crate::generators::WasmOptTtf,
configs: &[crate::generators::DifferentialConfig], configs: &[crate::generators::DifferentialConfig],
) { ) {
drop(env_logger::try_init()); crate::init_fuzzing();
// We need at least two configs. // We need at least two configs.
if configs.len() < 2 if configs.len() < 2
// And all the configs should be unique. // And all the configs should be unique.
@@ -280,7 +285,7 @@ fn assert_same_export_func_result(
pub fn make_api_calls(api: crate::generators::api::ApiCalls) { pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
use crate::generators::api::ApiCall; use crate::generators::api::ApiCall;
drop(env_logger::try_init()); crate::init_fuzzing();
let mut config: Option<Config> = None; let mut config: Option<Config> = None;
let mut engine: Option<Engine> = None; let mut engine: Option<Engine> = None;