Skip to content

Commit 9b9eecf

Browse files
committed
Store allocation size, make bytes, undef_mask private
Direct access to the bytes was previously a problem (rust-lang#62931) where components would read their contents without properly checking relocations and/or definedness. Making bytes private instead of purely renaming them also helps in allowing amendments to their allocation scheme (such as eliding allocation for undef of constant regions).
1 parent c43d03a commit 9b9eecf

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,21 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::Allocation {
176176
hasher: &mut StableHasher<W>,
177177
) {
178178
let mir::interpret::Allocation {
179-
bytes, relocations, undef_mask, align, mutability,
179+
relocations, align, mutability, size,
180180
extra: _,
181+
.. /* private bytes and undef_mask */
181182
} = self;
183+
184+
let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(0..self.len());
185+
let undef_mask = self.undef_mask();
186+
182187
bytes.hash_stable(hcx, hasher);
183188
relocations.len().hash_stable(hcx, hasher);
184189
for reloc in relocations.iter() {
185190
reloc.hash_stable(hcx, hasher);
186191
}
187192
undef_mask.hash_stable(hcx, hasher);
193+
size.hash_stable(hcx, hasher);
188194
align.hash_stable(hcx, hasher);
189195
mutability.hash_stable(hcx, hasher);
190196
}

src/librustc/mir/interpret/allocation.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ use std::borrow::Cow;
1616
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
1717
pub struct Allocation<Tag=(),Extra=()> {
1818
/// The actual bytes of the allocation.
19-
/// Note that the bytes of a pointer represent the offset of the pointer
20-
pub bytes: Vec<u8>,
19+
/// Note that the bytes of a pointer represent the offset of the pointer.
20+
bytes: Vec<u8>,
2121
/// Maps from byte addresses to extra data for each pointer.
2222
/// Only the first byte of a pointer is inserted into the map; i.e.,
2323
/// every entry in this map applies to `pointer_size` consecutive bytes starting
2424
/// at the given offset.
2525
pub relocations: Relocations<Tag>,
26-
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
27-
pub undef_mask: UndefMask,
26+
/// Denotes which part of this allocation is initialized.
27+
undef_mask: UndefMask,
28+
/// The size of the allocation. Currently, must always equal `bytes.len()`.
29+
pub size: Size,
2830
/// The alignment of the allocation to detect unaligned reads.
2931
pub align: Align,
3032
/// Whether the allocation is mutable.
@@ -85,11 +87,12 @@ impl<Tag> Allocation<Tag> {
8587
/// Creates a read-only allocation initialized by the given bytes
8688
pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
8789
let bytes = slice.into().into_owned();
88-
let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true);
90+
let size = Size::from_bytes(bytes.len() as u64);
8991
Self {
9092
bytes,
9193
relocations: Relocations::new(),
92-
undef_mask,
94+
undef_mask: UndefMask::new(size, true),
95+
size,
9396
align,
9497
mutability: Mutability::Immutable,
9598
extra: (),
@@ -106,13 +109,29 @@ impl<Tag> Allocation<Tag> {
106109
bytes: vec![0; size.bytes() as usize],
107110
relocations: Relocations::new(),
108111
undef_mask: UndefMask::new(size, false),
112+
size,
109113
align,
110114
mutability: Mutability::Mutable,
111115
extra: (),
112116
}
113117
}
114118
}
115119

120+
/// Raw accessors. Provide access to otherwise private bytes.
121+
impl<Tag, Extra> Allocation<Tag, Extra> {
122+
pub fn len(&self) -> usize {
123+
self.size.bytes() as usize
124+
}
125+
126+
/// Look at a slice which may describe undefined bytes or describe a relocation. This differs
127+
/// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the
128+
/// edges) at all. It further ignores `AllocationExtra` callbacks.
129+
/// This must not be used for reads affecting the interpreter execution.
130+
pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] {
131+
&self.bytes[range]
132+
}
133+
}
134+
116135
impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {}
117136

118137
/// Byte accessors
@@ -132,9 +151,9 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
132151
);
133152
let end = end.bytes() as usize;
134153
assert!(
135-
end <= self.bytes.len(),
154+
end <= self.len(),
136155
"Out-of-bounds access at offset {}, size {} in allocation of size {}",
137-
offset.bytes(), size.bytes(), self.bytes.len()
156+
offset.bytes(), size.bytes(), self.len()
138157
);
139158
(offset.bytes() as usize)..end
140159
}

src/librustc/ty/print/pretty.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,10 +944,16 @@ pub trait PrettyPrinter<'tcx>:
944944
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
945945
},
946946
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
947-
Some(&data.bytes[start..end])
947+
// The `inspect` here is okay since we checked the bounds, and there are no
948+
// relocations (we have an active slice reference here). We don't use this
949+
// result to affect interpreter execution.
950+
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
948951
},
949952
(ConstValue::Slice { data, start, end }, ty::Str) => {
950-
let slice = &data.bytes[start..end];
953+
// The `inspect` here is okay since we checked the bounds, and there are no
954+
// relocations (we have an active `str` reference here). We don't use this
955+
// result to affect interpreter execution.
956+
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
951957
let s = ::std::str::from_utf8(slice)
952958
.expect("non utf8 str from miri");
953959
p!(write("{:?}", s));

0 commit comments

Comments
 (0)