diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 0ddc9211f981..e33991bb1b6f 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -176,15 +176,21 @@ impl<'a> HashStable> for mir::interpret::Allocation { hasher: &mut StableHasher, ) { let mir::interpret::Allocation { - bytes, relocations, undef_mask, align, mutability, + relocations, align, mutability, size, extra: _, + .. /* private bytes and undef_mask */ } = self; + + let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(0..self.len()); + let undef_mask = self.undef_mask(); + bytes.hash_stable(hcx, hasher); relocations.len().hash_stable(hcx, hasher); for reloc in relocations.iter() { reloc.hash_stable(hcx, hasher); } undef_mask.hash_stable(hcx, hasher); + size.hash_stable(hcx, hasher); align.hash_stable(hcx, hasher); mutability.hash_stable(hcx, hasher); } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ce04cca96e0f..61b237c0bb39 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -16,15 +16,17 @@ use std::borrow::Cow; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Allocation { /// The actual bytes of the allocation. - /// Note that the bytes of a pointer represent the offset of the pointer - pub bytes: Vec, + /// Note that the bytes of a pointer represent the offset of the pointer. + bytes: Vec, /// Maps from byte addresses to extra data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting /// at the given offset. pub relocations: Relocations, - /// Denotes undefined memory. Reading from undefined memory is forbidden in miri - pub undef_mask: UndefMask, + /// Denotes which part of this allocation is initialized. + undef_mask: UndefMask, + /// The size of the allocation. Currently, must always equal `bytes.len()`. + pub size: Size, /// The alignment of the allocation to detect unaligned reads. pub align: Align, /// Whether the allocation is mutable. @@ -85,11 +87,12 @@ impl Allocation { /// Creates a read-only allocation initialized by the given bytes pub fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { let bytes = slice.into().into_owned(); - let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true); + let size = Size::from_bytes(bytes.len() as u64); Self { bytes, relocations: Relocations::new(), - undef_mask, + undef_mask: UndefMask::new(size, true), + size, align, mutability: Mutability::Immutable, extra: (), @@ -106,6 +109,7 @@ impl Allocation { bytes: vec![0; size.bytes() as usize], relocations: Relocations::new(), undef_mask: UndefMask::new(size, false), + size, align, mutability: Mutability::Mutable, extra: (), @@ -113,6 +117,21 @@ impl Allocation { } } +/// Raw accessors. Provide access to otherwise private bytes. +impl Allocation { + pub fn len(&self) -> usize { + self.size.bytes() as usize + } + + /// Look at a slice which may describe undefined bytes or describe a relocation. This differs + /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the + /// edges) at all. It further ignores `AllocationExtra` callbacks. + /// This must not be used for reads affecting the interpreter execution. + pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { + &self.bytes[range] + } +} + impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {} /// Byte accessors @@ -132,9 +151,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { ); let end = end.bytes() as usize; assert!( - end <= self.bytes.len(), + end <= self.len(), "Out-of-bounds access at offset {}, size {} in allocation of size {}", - offset.bytes(), size.bytes(), self.bytes.len() + offset.bytes(), size.bytes(), self.len() ); (offset.bytes() as usize)..end } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index bf6741dde43b..a72ecdb5745b 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -944,10 +944,16 @@ pub trait PrettyPrinter<'tcx>: .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) }, (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - Some(&data.bytes[start..end]) + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active slice reference here). We don't use this + // result to affect interpreter execution. + Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) }, (ConstValue::Slice { data, start, end }, ty::Str) => { - let slice = &data.bytes[start..end]; + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); let s = ::std::str::from_utf8(slice) .expect("non utf8 str from miri"); p!(write("{:?}", s));