add some sanity checks in write_immediate_no_validate
This commit is contained in:
parent
4ea2bd1c8f
commit
d127600511
3 changed files with 37 additions and 4 deletions
|
@ -577,7 +577,7 @@ where
|
||||||
src: Immediate<M::Provenance>,
|
src: Immediate<M::Provenance>,
|
||||||
dest: &PlaceTy<'tcx, M::Provenance>,
|
dest: &PlaceTy<'tcx, M::Provenance>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
assert!(dest.layout.is_sized(), "Cannot write unsized data");
|
assert!(dest.layout.is_sized(), "Cannot write unsized immediate data");
|
||||||
trace!("write_immediate: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);
|
trace!("write_immediate: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);
|
||||||
|
|
||||||
// See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
|
// See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
|
||||||
|
@ -591,9 +591,34 @@ where
|
||||||
*self.force_allocation(dest)?
|
*self.force_allocation(dest)?
|
||||||
} else {
|
} else {
|
||||||
match M::access_local_mut(self, frame, local)? {
|
match M::access_local_mut(self, frame, local)? {
|
||||||
Operand::Immediate(local) => {
|
Operand::Immediate(local_val) => {
|
||||||
// Local can be updated in-place.
|
// Local can be updated in-place.
|
||||||
*local = src;
|
*local_val = src;
|
||||||
|
// Double-check that the value we are storing and the local fit to each other.
|
||||||
|
// (*After* doing the update for borrow checker reasons.)
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
let local_layout =
|
||||||
|
self.layout_of_local(&self.stack()[frame], local, None)?;
|
||||||
|
match (src, local_layout.abi) {
|
||||||
|
(Immediate::Scalar(scalar), Abi::Scalar(s)) => {
|
||||||
|
assert_eq!(scalar.size(), s.size(self))
|
||||||
|
}
|
||||||
|
(
|
||||||
|
Immediate::ScalarPair(a_val, b_val),
|
||||||
|
Abi::ScalarPair(a, b),
|
||||||
|
) => {
|
||||||
|
assert_eq!(a_val.size(), a.size(self));
|
||||||
|
assert_eq!(b_val.size(), b.size(self));
|
||||||
|
}
|
||||||
|
(Immediate::Uninit, _) => {}
|
||||||
|
(src, abi) => {
|
||||||
|
bug!(
|
||||||
|
"value {src:?} cannot be written into local with type {} (ABI {abi:?})",
|
||||||
|
local_layout.ty
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Operand::Indirect(mplace) => {
|
Operand::Indirect(mplace) => {
|
||||||
|
|
|
@ -571,7 +571,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||||
assert!(self.mutability == Mutability::Mut);
|
assert!(self.mutability == Mutability::Mut);
|
||||||
|
|
||||||
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
|
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
|
||||||
// as-is into memory.
|
// as-is into memory. This also double-checks that `val.size()` matches `range.size`.
|
||||||
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
|
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
|
||||||
Right(ptr) => {
|
Right(ptr) => {
|
||||||
let (provenance, offset) = ptr.into_parts();
|
let (provenance, offset) = ptr.into_parts();
|
||||||
|
|
|
@ -320,6 +320,14 @@ impl<Prov> Scalar<Prov> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn size(self) -> Size {
|
||||||
|
match self {
|
||||||
|
Scalar::Int(int) => int.size(),
|
||||||
|
Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue