-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fuzz: refactor fuzz generators (#4404)
Previously, much of the logic for generating the various objects needed for fuzzing was concentrated primarily in `generators.rs`. In trying to piece together what code does what, the size of the file and the light documentation make it hard to discern what each part does. Since several generator structures had been split out as separate modules in the `generators/` directory, this change takes that refactoring further by moving the structures in `generators.rs` to their own modules. No logic changes were made, only the addition of documentation in a few places.
- Loading branch information
Showing
8 changed files
with
847 additions
and
796 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
//! Generate Cranelift compiler settings. | ||
use arbitrary::{Arbitrary, Unstructured}; | ||
|
||
/// Choose between matching the host architecture or a cross-compilation target. | ||
#[derive(Clone, Debug, Eq, Hash, PartialEq)] | ||
pub enum CodegenSettings { | ||
/// Use the host's feature set. | ||
Native, | ||
/// Generate a modified flag set for the current host. | ||
#[allow(dead_code)] | ||
Target { | ||
/// The target triple of the host. | ||
target: String, | ||
/// A list of CPU features to enable, e.g., `("has_avx", "false")`. | ||
flags: Vec<(String, String)>, | ||
}, | ||
} | ||
|
||
impl CodegenSettings { | ||
/// Configure Wasmtime with these codegen settings. | ||
pub fn configure(&self, config: &mut wasmtime::Config) { | ||
match self { | ||
CodegenSettings::Native => {} | ||
CodegenSettings::Target { target, flags } => { | ||
config.target(target).unwrap(); | ||
for (key, value) in flags { | ||
unsafe { | ||
config.cranelift_flag_set(key, value); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl<'a> Arbitrary<'a> for CodegenSettings { | ||
#[allow(unused_macros, unused_variables)] | ||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { | ||
// Helper macro to enable clif features based on what the native host | ||
// supports. If the input says to enable a feature and the host doesn't | ||
// support it then that test case is rejected with a warning. | ||
// | ||
// Note that this specifically consumes bytes from the fuzz input for | ||
// features for all targets, discarding anything which isn't applicable | ||
// to the current target. The theory behind this is that most fuzz bugs | ||
// won't be related to this feature selection so by consistently | ||
// consuming input irrespective of the current platform reproducing fuzz | ||
// bugs should be easier between different architectures. | ||
macro_rules! target_features { | ||
( | ||
$( | ||
$arch:tt => { | ||
test:$test:ident, | ||
$(std: $std:tt => clif: $clif:tt $(ratio: $a:tt in $b:tt)?,)* | ||
}, | ||
)* | ||
) => ({ | ||
let mut flags = Vec::new(); | ||
$( // for each `$arch` | ||
$( // for each `$std`/`$clif` pair | ||
// Use the input to generate whether `$clif` will be | ||
// enabled. By default this is a 1 in 2 chance but each | ||
// feature supports a custom ratio as well which shadows | ||
// the (low, hi) | ||
let (low, hi) = (1, 2); | ||
$(let (low, hi) = ($a, $b);)? | ||
let enable = u.ratio(low, hi)?; | ||
|
||
// If we're actually on the relevant platform and the | ||
// feature is enabled be sure to check that this host | ||
// supports it. If the host doesn't support it then | ||
// print a warning and return an error because this fuzz | ||
// input must be discarded. | ||
#[cfg(target_arch = $arch)] | ||
if enable && !std::arch::$test!($std) { | ||
log::warn!("want to enable clif `{}` but host doesn't support it", | ||
$clif); | ||
return Err(arbitrary::Error::EmptyChoose) | ||
} | ||
|
||
// And finally actually push the feature into the set of | ||
// flags to enable, but only if we're on the right | ||
// architecture. | ||
if cfg!(target_arch = $arch) { | ||
flags.push(( | ||
$clif.to_string(), | ||
enable.to_string(), | ||
)); | ||
} | ||
)* | ||
)* | ||
flags | ||
}) | ||
} | ||
if u.ratio(1, 10)? { | ||
let flags = target_features! { | ||
"x86_64" => { | ||
test: is_x86_feature_detected, | ||
|
||
// These features are considered to be baseline required by | ||
// Wasmtime. Currently some SIMD code generation will | ||
// fail if these features are disabled, so unconditionally | ||
// enable them as we're not interested in fuzzing without | ||
// them. | ||
std:"sse3" => clif:"has_sse3" ratio: 1 in 1, | ||
std:"ssse3" => clif:"has_ssse3" ratio: 1 in 1, | ||
std:"sse4.1" => clif:"has_sse41" ratio: 1 in 1, | ||
std:"sse4.2" => clif:"has_sse42" ratio: 1 in 1, | ||
|
||
std:"popcnt" => clif:"has_popcnt", | ||
std:"avx" => clif:"has_avx", | ||
std:"avx2" => clif:"has_avx2", | ||
std:"bmi1" => clif:"has_bmi1", | ||
std:"bmi2" => clif:"has_bmi2", | ||
std:"lzcnt" => clif:"has_lzcnt", | ||
|
||
// not a lot of of cpus support avx512 so these are weighted | ||
// to get enabled much less frequently. | ||
std:"avx512bitalg" => clif:"has_avx512bitalg" ratio:1 in 1000, | ||
std:"avx512dq" => clif:"has_avx512dq" ratio: 1 in 1000, | ||
std:"avx512f" => clif:"has_avx512f" ratio: 1 in 1000, | ||
std:"avx512vl" => clif:"has_avx512vl" ratio: 1 in 1000, | ||
std:"avx512vbmi" => clif:"has_avx512vbmi" ratio: 1 in 1000, | ||
}, | ||
"aarch64" => { | ||
test: is_aarch64_feature_detected, | ||
|
||
std: "lse" => clif: "has_lse", | ||
}, | ||
}; | ||
return Ok(CodegenSettings::Target { | ||
target: target_lexicon::Triple::host().to_string(), | ||
flags, | ||
}); | ||
} | ||
Ok(CodegenSettings::Native) | ||
} | ||
} |
Oops, something went wrong.