Skip to content

Commit d127600

Browse files
committed
add some sanity checks in write_immediate_no_validate
1 parent 4ea2bd1 commit d127600

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

compiler/rustc_const_eval/src/interpret/place.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ where
577577
src: Immediate<M::Provenance>,
578578
dest: &PlaceTy<'tcx, M::Provenance>,
579579
) -> InterpResult<'tcx> {
580-
assert!(dest.layout.is_sized(), "Cannot write unsized data");
580+
assert!(dest.layout.is_sized(), "Cannot write unsized immediate data");
581581
trace!("write_immediate: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);
582582

583583
// See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
@@ -591,9 +591,34 @@ where
591591
*self.force_allocation(dest)?
592592
} else {
593593
match M::access_local_mut(self, frame, local)? {
594-
Operand::Immediate(local) => {
594+
Operand::Immediate(local_val) => {
595595
// Local can be updated in-place.
596-
*local = src;
596+
*local_val = src;
597+
// Double-check that the value we are storing and the local fit to each other.
598+
// (*After* doing the update for borrow checker reasons.)
599+
if cfg!(debug_assertions) {
600+
let local_layout =
601+
self.layout_of_local(&self.stack()[frame], local, None)?;
602+
match (src, local_layout.abi) {
603+
(Immediate::Scalar(scalar), Abi::Scalar(s)) => {
604+
assert_eq!(scalar.size(), s.size(self))
605+
}
606+
(
607+
Immediate::ScalarPair(a_val, b_val),
608+
Abi::ScalarPair(a, b),
609+
) => {
610+
assert_eq!(a_val.size(), a.size(self));
611+
assert_eq!(b_val.size(), b.size(self));
612+
}
613+
(Immediate::Uninit, _) => {}
614+
(src, abi) => {
615+
bug!(
616+
"value {src:?} cannot be written into local with type {} (ABI {abi:?})",
617+
local_layout.ty
618+
)
619+
}
620+
};
621+
}
597622
return Ok(());
598623
}
599624
Operand::Indirect(mplace) => {

compiler/rustc_middle/src/mir/interpret/allocation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
571571
assert!(self.mutability == Mutability::Mut);
572572

573573
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
574-
// as-is into memory.
574+
// as-is into memory. This also double-checks that `val.size()` matches `range.size`.
575575
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
576576
Right(ptr) => {
577577
let (provenance, offset) = ptr.into_parts();

compiler/rustc_middle/src/mir/interpret/value.rs

+8
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ impl<Prov> Scalar<Prov> {
320320
}
321321
})
322322
}
323+
324+
#[inline]
325+
pub fn size(self) -> Size {
326+
match self {
327+
Scalar::Int(int) => int.size(),
328+
Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz),
329+
}
330+
}
323331
}
324332

325333
impl<'tcx, Prov: Provenance> Scalar<Prov> {

0 commit comments

Comments
 (0)