Auto merge of #113720 - eduardosm:miri-target-feature, r=RalfJung,oli-obk
miri: fail when calling a function that requires an unavailable target feature miri will report an UB when calling a function that has a `#[target_feature(enable = ...)]` attribute is called and the required feature is not available. "Available features" are the same that `is_x86_feature_detected!` (or equivalent) reports to be available during miri execution (which can be enabled or disabled with the `-C target-feature` flag).
This commit is contained in:
commit
1787f31290
@ -399,6 +399,9 @@ const_eval_unallowed_mutable_refs_raw =
|
|||||||
const_eval_unallowed_op_in_const_context =
|
const_eval_unallowed_op_in_const_context =
|
||||||
{$msg}
|
{$msg}
|
||||||
|
|
||||||
|
const_eval_unavailable_target_features_for_fn =
|
||||||
|
calling a function that requires unavailable target features: {$unavailable_feats}
|
||||||
|
|
||||||
const_eval_undefined_behavior =
|
const_eval_undefined_behavior =
|
||||||
it is undefined behavior to use this value
|
it is undefined behavior to use this value
|
||||||
|
|
||||||
|
@ -503,6 +503,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that all target features required by the callee (i.e., from
|
||||||
|
// the attribute `#[target_feature(enable = ...)]`) are enabled at
|
||||||
|
// compile time.
|
||||||
|
self.check_fn_target_features(instance)?;
|
||||||
|
|
||||||
if !callee_fn_abi.can_unwind {
|
if !callee_fn_abi.can_unwind {
|
||||||
// The callee cannot unwind, so force the `Unreachable` unwind handling.
|
// The callee cannot unwind, so force the `Unreachable` unwind handling.
|
||||||
unwind = mir::UnwindAction::Unreachable;
|
unwind = mir::UnwindAction::Unreachable;
|
||||||
@ -786,6 +791,31 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> {
|
||||||
|
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||||
|
if attrs
|
||||||
|
.target_features
|
||||||
|
.iter()
|
||||||
|
.any(|feature| !self.tcx.sess.target_features.contains(feature))
|
||||||
|
{
|
||||||
|
throw_ub_custom!(
|
||||||
|
fluent::const_eval_unavailable_target_features_for_fn,
|
||||||
|
unavailable_feats = attrs
|
||||||
|
.target_features
|
||||||
|
.iter()
|
||||||
|
.filter(|&feature| !self.tcx.sess.target_features.contains(feature))
|
||||||
|
.fold(String::new(), |mut s, feature| {
|
||||||
|
if !s.is_empty() {
|
||||||
|
s.push_str(", ");
|
||||||
|
}
|
||||||
|
s.push_str(feature.as_str());
|
||||||
|
s
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn drop_in_place(
|
fn drop_in_place(
|
||||||
&mut self,
|
&mut self,
|
||||||
place: &PlaceTy<'tcx, M::Provenance>,
|
place: &PlaceTy<'tcx, M::Provenance>,
|
||||||
|
11
src/tools/miri/tests/fail/function_calls/target_feature.rs
Normal file
11
src/tools/miri/tests/fail/function_calls/target_feature.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//@only-target-x86_64: uses x86 target features
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert!(!is_x86_feature_detected!("ssse3"));
|
||||||
|
unsafe {
|
||||||
|
ssse3_fn(); //~ ERROR: calling a function that requires unavailable target features: ssse3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[target_feature(enable = "ssse3")]
|
||||||
|
unsafe fn ssse3_fn() {}
|
@ -0,0 +1,15 @@
|
|||||||
|
error: Undefined Behavior: calling a function that requires unavailable target features: ssse3
|
||||||
|
--> $DIR/target_feature.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | ssse3_fn();
|
||||||
|
| ^^^^^^^^^^ calling a function that requires unavailable target features: ssse3
|
||||||
|
|
|
||||||
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= note: BACKTRACE:
|
||||||
|
= note: inside `main` at $DIR/target_feature.rs:LL:CC
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
12
src/tools/miri/tests/pass/function_calls/target_feature.rs
Normal file
12
src/tools/miri/tests/pass/function_calls/target_feature.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//@only-target-x86_64: uses x86 target features
|
||||||
|
//@compile-flags: -C target-feature=+ssse3
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert!(is_x86_feature_detected!("ssse3"));
|
||||||
|
unsafe {
|
||||||
|
ssse3_fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[target_feature(enable = "ssse3")]
|
||||||
|
unsafe fn ssse3_fn() {}
|
17
tests/ui/consts/const-eval/const_fn_target_feature.rs
Normal file
17
tests/ui/consts/const-eval/const_fn_target_feature.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// only-x86_64
|
||||||
|
// compile-flags:-C target-feature=+ssse3
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// ok (ssse3 enabled at compile time)
|
||||||
|
const A: () = unsafe { ssse3_fn() };
|
||||||
|
|
||||||
|
// error (avx2 not enabled at compile time)
|
||||||
|
const B: () = unsafe { avx2_fn() };
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
|
#[target_feature(enable = "ssse3")]
|
||||||
|
const unsafe fn ssse3_fn() {}
|
||||||
|
|
||||||
|
#[target_feature(enable = "avx2")]
|
||||||
|
const unsafe fn avx2_fn() {}
|
@ -0,0 +1,9 @@
|
|||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const_fn_target_feature.rs:10:24
|
||||||
|
|
|
||||||
|
LL | const B: () = unsafe { avx2_fn() };
|
||||||
|
| ^^^^^^^^^ calling a function that requires unavailable target features: avx2
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
Loading…
x
Reference in New Issue
Block a user