Skip to content

Commit 739144f

Browse files
committed
MIR validation: reject in-place argument/return for packed fields
1 parent 0b31792 commit 739144f

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 28 additions & 3 deletions
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
}
@@ -418,22 +421,42 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
418421
self.check_unwind_edge(location, *unwind);
419422

420423
// The call destination place and Operand::Move place used as an argument might be
421-
// passed by a reference to the callee. Consequently they must be non-overlapping.
422-
// Currently this simply checks for duplicate places.
424+
// passed by a reference to the callee. Consequently they must be non-overlapping
425+
// and cannot be packed. Currently this simply checks for duplicate places.
423426
self.place_cache.clear();
424427
self.place_cache.insert(destination.as_ref());
428+
if is_within_packed(self.tcx, &self.body.local_decls, *destination).is_some() {
429+
// This is bad! The callee will expect the memory to be aligned.
430+
self.fail(
431+
location,
432+
format!(
433+
"encountered packed place in `Call` terminator destination: {:?}",
434+
terminator.kind,
435+
),
436+
);
437+
}
425438
let mut has_duplicates = false;
426439
for arg in args {
427440
if let Operand::Move(place) = arg {
428441
has_duplicates |= !self.place_cache.insert(place.as_ref());
442+
if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() {
443+
// This is bad! The callee will expect the memory to be aligned.
444+
self.fail(
445+
location,
446+
format!(
447+
"encountered `Move` of a packed place in `Call` terminator: {:?}",
448+
terminator.kind,
449+
),
450+
);
451+
}
429452
}
430453
}
431454

432455
if has_duplicates {
433456
self.fail(
434457
location,
435458
format!(
436-
"encountered overlapping memory in `Call` terminator: {:?}",
459+
"encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}",
437460
terminator.kind,
438461
),
439462
);
@@ -532,6 +555,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
532555
}
533556
}
534557

558+
/// A faster version of the validation pass that only checks those things which may break when apply
559+
/// generic substitutions.
535560
pub fn validate_types<'tcx>(
536561
tcx: TyCtxt<'tcx>,
537562
mir_phase: MirPhase,

compiler/rustc_const_eval/src/util/alignment.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ 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
}
4041
}
4142
}
4243

43-
fn is_within_packed<'tcx, L>(
44+
pub fn is_within_packed<'tcx, L>(
4445
tcx: TyCtxt<'tcx>,
4546
local_decls: &L,
4647
place: Place<'tcx>,

compiler/rustc_const_eval/src/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod check_validity_requirement;
55
mod compare_types;
66
mod type_name;
77

8-
pub use self::alignment::is_disaligned;
8+
pub use self::alignment::{is_disaligned, is_within_packed};
99
pub use self::check_validity_requirement::check_validity_requirement;
1010
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
1111
pub use self::type_name::type_name;

0 commit comments

Comments
 (0)