Add a spec test fuzzer for Config (#1509)

* Add a spec test fuzzer for Config

This commit adds a new fuzzer which is intended to run on oss-fuzz. This
fuzzer creates and arbitrary `Config` which *should* pass spec tests and
then asserts that it does so. The goal here is to weed out any
accidental bugs in global configuration which could cause
non-spec-compliant behavior.

* Move implementation to `fuzzing` crate
This commit is contained in:
Alex Crichton
2020-04-15 08:29:12 -05:00
committed by GitHub
parent be85242a3f
commit 6dde222992
7 changed files with 118 additions and 9 deletions

View File

@@ -11,7 +11,7 @@
#[cfg(feature = "binaryen")]
pub mod api;
use arbitrary::Arbitrary;
use arbitrary::{Arbitrary, Unstructured};
/// A Wasm test case generator that is powered by Binaryen's `wasm-opt -ttf`.
#[derive(Clone)]
@@ -60,7 +60,7 @@ impl Arbitrary for WasmOptTtf {
#[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)]
pub struct DifferentialConfig {
strategy: DifferentialStrategy,
opt_level: DifferentialOptLevel,
opt_level: OptLevel,
}
impl DifferentialConfig {
@@ -70,11 +70,7 @@ impl DifferentialConfig {
DifferentialStrategy::Cranelift => wasmtime::Strategy::Cranelift,
DifferentialStrategy::Lightbeam => wasmtime::Strategy::Lightbeam,
})?;
config.cranelift_opt_level(match self.opt_level {
DifferentialOptLevel::None => wasmtime::OptLevel::None,
DifferentialOptLevel::Speed => wasmtime::OptLevel::Speed,
DifferentialOptLevel::SpeedAndSize => wasmtime::OptLevel::SpeedAndSize,
});
config.cranelift_opt_level(self.opt_level.to_wasmtime());
Ok(config)
}
}
@@ -86,8 +82,65 @@ enum DifferentialStrategy {
}
#[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)]
enum DifferentialOptLevel {
enum OptLevel {
None,
Speed,
SpeedAndSize,
}
impl OptLevel {
fn to_wasmtime(&self) -> wasmtime::OptLevel {
match self {
OptLevel::None => wasmtime::OptLevel::None,
OptLevel::Speed => wasmtime::OptLevel::Speed,
OptLevel::SpeedAndSize => wasmtime::OptLevel::SpeedAndSize,
}
}
}
/// Implementation of generating a `wasmtime::Config` arbitrarily
#[derive(Arbitrary, Debug)]
pub struct Config {
opt_level: OptLevel,
debug_verifier: bool,
debug_info: bool,
canonicalize_nans: bool,
spectest: usize,
}
impl Config {
/// Converts this to a `wasmtime::Config` object
pub fn to_wasmtime(&self) -> wasmtime::Config {
let mut cfg = wasmtime::Config::new();
cfg.debug_info(self.debug_info)
.cranelift_nan_canonicalization(self.canonicalize_nans)
.cranelift_debug_verifier(self.debug_verifier)
.cranelift_opt_level(self.opt_level.to_wasmtime());
return cfg;
}
}
include!(concat!(env!("OUT_DIR"), "/spectests.rs"));
/// A spec test from the upstream wast testsuite, arbitrarily chosen from the
/// list of known spec tests.
#[derive(Debug)]
pub struct SpecTest {
/// The filename of the spec test
pub file: &'static str,
/// The `*.wast` contents of the spec test
pub contents: &'static str,
}
impl Arbitrary for SpecTest {
fn arbitrary(u: &mut Unstructured) -> arbitrary::Result<Self> {
// NB: this does get a uniform value in the provided range.
let i = u.int_in_range(0..=FILES.len() - 1)?;
let (file, contents) = FILES[i];
Ok(SpecTest { file, contents })
}
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
(1, Some(std::mem::size_of::<usize>()))
}
}