Skip to content

Commit ea84409

Browse files
committed
interpret: reset padding during validation
1 parent dde15ce commit ea84409

20 files changed

+497
-39
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
use std::borrow::Borrow;
1+
use std::borrow::{Borrow, Cow};
22
use std::fmt;
33
use std::hash::Hash;
44
use std::ops::ControlFlow;
55

66
use rustc_ast::Mutability;
7-
use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
7+
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
88
use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID};
1010
use rustc_middle::mir::AssertMessage;
1111
use rustc_middle::query::TyCtxtAt;
1212
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
13-
use rustc_middle::ty::{self, TyCtxt};
13+
use rustc_middle::ty::{self, Ty, TyCtxt};
1414
use rustc_middle::{bug, mir};
1515
use rustc_span::symbol::{sym, Symbol};
1616
use rustc_span::Span;
@@ -24,8 +24,8 @@ use crate::fluent_generated as fluent;
2424
use crate::interpret::{
2525
self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup,
2626
throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
27-
GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
28-
StackPopCleanup,
27+
GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic,
28+
RangeSet, Scalar, StackPopCleanup,
2929
};
3030

3131
/// When hitting this many interpreted terminators we emit a deny by default lint
@@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> {
6565
/// storing the result in the given `AllocId`.
6666
/// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
6767
pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
68+
69+
/// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
70+
union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
6871
}
6972

7073
#[derive(Copy, Clone)]
@@ -99,6 +102,7 @@ impl<'tcx> CompileTimeMachine<'tcx> {
99102
can_access_mut_global,
100103
check_alignment,
101104
static_root_ids: None,
105+
union_data_ranges: FxHashMap::default(),
102106
}
103107
}
104108
}
@@ -766,6 +770,19 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
766770
}
767771
Ok(())
768772
}
773+
774+
fn cached_union_data_range<'e>(
775+
ecx: &'e mut InterpCx<'tcx, Self>,
776+
ty: Ty<'tcx>,
777+
compute_range: impl FnOnce() -> RangeSet,
778+
) -> Cow<'e, RangeSet> {
779+
if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks {
780+
Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
781+
} else {
782+
// Don't bother caching, we're only doing one validation at the end anyway.
783+
Cow::Owned(compute_range())
784+
}
785+
}
769786
}
770787

771788
// Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups

compiler/rustc_const_eval/src/interpret/machine.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_apfloat::{Float, FloatConvert};
1010
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1111
use rustc_middle::query::TyCtxtAt;
1212
use rustc_middle::ty::layout::TyAndLayout;
13+
use rustc_middle::ty::Ty;
1314
use rustc_middle::{mir, ty};
1415
use rustc_span::def_id::DefId;
1516
use rustc_span::Span;
@@ -19,7 +20,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
1920
use super::{
2021
throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
2122
ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
22-
MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT,
23+
MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT,
2324
};
2425

2526
/// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -588,6 +589,15 @@ pub trait Machine<'tcx>: Sized {
588589
ecx: &InterpCx<'tcx, Self>,
589590
instance: Option<ty::Instance<'tcx>>,
590591
) -> usize;
592+
593+
fn cached_union_data_range<'e>(
594+
_ecx: &'e mut InterpCx<'tcx, Self>,
595+
_ty: Ty<'tcx>,
596+
compute_range: impl FnOnce() -> RangeSet,
597+
) -> Cow<'e, RangeSet> {
598+
// Default to no caching.
599+
Cow::Owned(compute_range())
600+
}
591601
}
592602

593603
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines

compiler/rustc_const_eval/src/interpret/memory.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1136,8 +1136,17 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
11361136
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
11371137
}
11381138

1139+
/// Mark the given sub-range (relative to this allocation reference) as uninitialized.
1140+
pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> {
1141+
let range = self.range.subrange(range);
1142+
Ok(self
1143+
.alloc
1144+
.write_uninit(&self.tcx, range)
1145+
.map_err(|e| e.to_interp_error(self.alloc_id))?)
1146+
}
1147+
11391148
/// Mark the entire referenced range as uninitialized
1140-
pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
1149+
pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> {
11411150
Ok(self
11421151
.alloc
11431152
.write_uninit(&self.tcx, self.range)

compiler/rustc_const_eval/src/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ use self::place::{MemPlace, Place};
3939
pub use self::projection::{OffsetMode, Projectable};
4040
pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
4141
pub(crate) use self::util::create_static_alloc;
42-
pub use self::validity::{CtfeValidationMode, RefTracking};
42+
pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
4343
pub use self::visitor::ValueVisitor;

compiler/rustc_const_eval/src/interpret/place.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,11 @@ where
602602

603603
if M::enforce_validity(self, dest.layout()) {
604604
// Data got changed, better make sure it matches the type!
605+
// Also needed to reset padding.
605606
self.validate_operand(
606607
&dest.to_place(),
607608
M::enforce_validity_recursively(self, dest.layout()),
608-
/*reset_provenance*/ true,
609+
/*reset_provenance_and_padding*/ true,
609610
)?;
610611
}
611612

@@ -701,9 +702,11 @@ where
701702
// fields do not match the `ScalarPair` components.
702703

703704
alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?;
704-
alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)
705+
alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?;
706+
// We don't have to reset padding here, `write_immediate` will anyway do a validation run.
707+
Ok(())
705708
}
706-
Immediate::Uninit => alloc.write_uninit(),
709+
Immediate::Uninit => alloc.write_uninit_full(),
707710
}
708711
}
709712

@@ -720,7 +723,7 @@ where
720723
// Zero-sized access
721724
return Ok(());
722725
};
723-
alloc.write_uninit()?;
726+
alloc.write_uninit_full()?;
724727
}
725728
}
726729
Ok(())
@@ -812,17 +815,17 @@ where
812815
// Given that there were two typed copies, we have to ensure this is valid at both types,
813816
// and we have to ensure this loses provenance and padding according to both types.
814817
// But if the types are identical, we only do one pass.
815-
if src.layout().ty != dest.layout().ty {
818+
if allow_transmute && src.layout().ty != dest.layout().ty {
816819
self.validate_operand(
817820
&dest.transmute(src.layout(), self)?,
818821
M::enforce_validity_recursively(self, src.layout()),
819-
/*reset_provenance*/ true,
822+
/*reset_provenance_and_padding*/ true,
820823
)?;
821824
}
822825
self.validate_operand(
823826
&dest,
824827
M::enforce_validity_recursively(self, dest.layout()),
825-
/*reset_provenance*/ true,
828+
/*reset_provenance_and_padding*/ true,
826829
)?;
827830
}
828831

0 commit comments

Comments
 (0)