Improve platform compatibility of fuzz test cases (#3824)
In #3800 I added support to consume fuzz input as selection of whether or not target features should be enabled. This was done in a platform-specific manner, however, which means that I can no longer reliably take the fuzz reproducer cases from oss-fuzz and reproduce them locally on an aarch64 machine. This commit fixes this problem by unconditionally pulling bytes from the input for fuzz features, irrespective of the host platform. Features are then discarded if they're not applicable.
This commit is contained in:
@@ -671,33 +671,62 @@ impl<'a> Arbitrary<'a> for CodegenSettings {
|
|||||||
// Helper macro to enable clif features based on what the native host
|
// 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
|
// 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.
|
// 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 {
|
macro_rules! target_features {
|
||||||
(
|
(
|
||||||
test:$test:ident,
|
$(
|
||||||
$(std: $std:tt => clif: $clif:tt $(ratio: $a:tt in $b:tt)?,)*
|
$arch:tt => {
|
||||||
|
test:$test:ident,
|
||||||
|
$(std: $std:tt => clif: $clif:tt $(ratio: $a:tt in $b:tt)?,)*
|
||||||
|
},
|
||||||
|
)*
|
||||||
) => ({
|
) => ({
|
||||||
let mut flags = Vec::new();
|
let mut flags = Vec::new();
|
||||||
$(
|
$( // for each `$arch`
|
||||||
let (low, hi) = (1, 2);
|
$( // for each `$std`/`$clif` pair
|
||||||
$(let (low, hi) = ($a, $b);)?
|
// Use the input to generate whether `$clif` will be
|
||||||
let enable = u.ratio(low, hi)?;
|
// enabled. By default this is a 1 in 2 chance but each
|
||||||
if enable && !std::$test!($std) {
|
// feature supports a custom ratio as well which shadows
|
||||||
log::error!("want to enable clif `{}` but host doesn't support it",
|
// the (low, hi)
|
||||||
$clif);
|
let (low, hi) = (1, 2);
|
||||||
return Err(arbitrary::Error::EmptyChoose)
|
$(let (low, hi) = ($a, $b);)?
|
||||||
}
|
let enable = u.ratio(low, hi)?;
|
||||||
flags.push((
|
|
||||||
$clif.to_string(),
|
// If we're actually on the relevant platform and the
|
||||||
enable.to_string(),
|
// 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::$test!($std) {
|
||||||
|
log::error!("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
|
flags
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86_64")]
|
if u.ratio(1, 10)? {
|
||||||
{
|
let flags = target_features! {
|
||||||
if u.ratio(1, 10)? {
|
"x86_64" => {
|
||||||
let flags = target_features! {
|
|
||||||
test: is_x86_feature_detected,
|
test: is_x86_feature_detected,
|
||||||
|
|
||||||
// These features are considered to be baseline required by
|
// These features are considered to be baseline required by
|
||||||
@@ -724,12 +753,12 @@ impl<'a> Arbitrary<'a> for CodegenSettings {
|
|||||||
std:"avx512f" => clif:"has_avx512f" ratio: 1 in 1000,
|
std:"avx512f" => clif:"has_avx512f" ratio: 1 in 1000,
|
||||||
std:"avx512vl" => clif:"has_avx512vl" ratio: 1 in 1000,
|
std:"avx512vl" => clif:"has_avx512vl" ratio: 1 in 1000,
|
||||||
std:"avx512vbmi" => clif:"has_avx512vbmi" ratio: 1 in 1000,
|
std:"avx512vbmi" => clif:"has_avx512vbmi" ratio: 1 in 1000,
|
||||||
};
|
},
|
||||||
return Ok(CodegenSettings::Target {
|
};
|
||||||
target: target_lexicon::Triple::host().to_string(),
|
return Ok(CodegenSettings::Target {
|
||||||
flags,
|
target: target_lexicon::Triple::host().to_string(),
|
||||||
});
|
flags,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
Ok(CodegenSettings::Native)
|
Ok(CodegenSettings::Native)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user