Skip to content

Commit f2c6cbd

Browse files
Prevent calls to functions with #[target_feature] in safe contexts
1 parent 2474f0e commit f2c6cbd

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/librustc_mir/transform/check_unsafety.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::util;
1919

2020
pub struct UnsafetyChecker<'a, 'tcx> {
2121
body: &'a Body<'tcx>,
22+
body_did: LocalDefId,
2223
const_context: bool,
2324
min_const_fn: bool,
2425
violations: Vec<UnsafetyViolation>,
@@ -35,6 +36,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
3536
const_context: bool,
3637
min_const_fn: bool,
3738
body: &'a Body<'tcx>,
39+
body_did: LocalDefId,
3840
tcx: TyCtxt<'tcx>,
3941
param_env: ty::ParamEnv<'tcx>,
4042
) -> Self {
@@ -44,6 +46,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
4446
}
4547
Self {
4648
body,
49+
body_did,
4750
const_context,
4851
min_const_fn,
4952
violations: vec![],
@@ -87,6 +90,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
8790
UnsafetyViolationKind::GeneralAndConstFn,
8891
)
8992
}
93+
94+
if let ty::FnDef(func_id, _) = func_ty.kind {
95+
self.check_target_features(func_id);
96+
}
9097
}
9198
}
9299
self.super_terminator(terminator, location);
@@ -436,6 +443,22 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
436443
}
437444
}
438445
}
446+
447+
/// Checks whether calling `func_did` needs an `unsafe` context or not, i.e. whether
448+
/// the called function has target features the calling function hasn't.
449+
fn check_target_features(&mut self, func_did: DefId) {
450+
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
451+
let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features;
452+
453+
// Is `callee_features` a subset of `calling_features`?
454+
if !callee_features.iter().all(|feature| self_features.contains(feature)) {
455+
self.require_unsafe(
456+
"call to function with `#[target_feature]`",
457+
"can only be called if the required target features are available",
458+
UnsafetyViolationKind::GeneralAndConstFn,
459+
)
460+
}
461+
}
439462
}
440463

441464
pub(crate) fn provide(providers: &mut Providers<'_>) {
@@ -502,7 +525,8 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: LocalDefId) -> UnsafetyCheckRe
502525
}
503526
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => (true, false),
504527
};
505-
let mut checker = UnsafetyChecker::new(const_context, min_const_fn, body, tcx, param_env);
528+
let mut checker =
529+
UnsafetyChecker::new(const_context, min_const_fn, body, def_id, tcx, param_env);
506530
checker.visit_body(&body);
507531

508532
check_unused_unsafe(tcx, def_id, &checker.used_unsafe, &mut checker.inherited_blocks);

0 commit comments

Comments
 (0)