Skip to content

Commit 88b476c

Browse files
authored
Rollup merge of #115164 - RalfJung:no-in-place-packed, r=b-naber
MIR validation: reject in-place argument/return for packed fields As discussed [here](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-opsem/topic/Packed.20fields.20and.20in-place.20function.20argument.2Freturn.20passing).
2 parents c587fd4 + 739144f commit 88b476c

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor};
2020
use rustc_target::abi::{Size, FIRST_VARIANT};
2121
use rustc_target::spec::abi::Abi;
2222

23+
use crate::util::is_within_packed;
24+
2325
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2426
enum EdgeKind {
2527
Unwind,
@@ -93,6 +95,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
9395
cfg_checker.visit_body(body);
9496
cfg_checker.check_cleanup_control_flow();
9597

98+
// Also run the TypeChecker.
9699
for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body) {
97100
cfg_checker.fail(location, msg);
98101
}
@@ -427,22 +430,42 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
427430
self.check_unwind_edge(location, *unwind);
428431

429432
// The call destination place and Operand::Move place used as an argument might be
430-
// passed by a reference to the callee. Consequently they must be non-overlapping.
431-
// Currently this simply checks for duplicate places.
433+
// passed by a reference to the callee. Consequently they must be non-overlapping
434+
// and cannot be packed. Currently this simply checks for duplicate places.
432435
self.place_cache.clear();
433436
self.place_cache.insert(destination.as_ref());
437+
if is_within_packed(self.tcx, &self.body.local_decls, *destination).is_some() {
438+
// This is bad! The callee will expect the memory to be aligned.
439+
self.fail(
440+
location,
441+
format!(
442+
"encountered packed place in `Call` terminator destination: {:?}",
443+
terminator.kind,
444+
),
445+
);
446+
}
434447
let mut has_duplicates = false;
435448
for arg in args {
436449
if let Operand::Move(place) = arg {
437450
has_duplicates |= !self.place_cache.insert(place.as_ref());
451+
if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() {
452+
// This is bad! The callee will expect the memory to be aligned.
453+
self.fail(
454+
location,
455+
format!(
456+
"encountered `Move` of a packed place in `Call` terminator: {:?}",
457+
terminator.kind,
458+
),
459+
);
460+
}
438461
}
439462
}
440463

441464
if has_duplicates {
442465
self.fail(
443466
location,
444467
format!(
445-
"encountered overlapping memory in `Call` terminator: {:?}",
468+
"encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}",
446469
terminator.kind,
447470
),
448471
);
@@ -541,6 +564,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
541564
}
542565
}
543566

567+
/// A faster version of the validation pass that only checks those things which may break when apply
568+
/// generic substitutions.
544569
pub fn validate_types<'tcx>(
545570
tcx: TyCtxt<'tcx>,
546571
mir_phase: MirPhase,

compiler/rustc_const_eval/src/util/alignment.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ where
3434
false
3535
}
3636
_ => {
37+
// We cannot figure out the layout. Conservatively assume that this is disaligned.
3738
debug!("is_disaligned({:?}) - true", place);
3839
true
3940
}

0 commit comments

Comments
 (0)