Skip to content

Commit e36e63e

Browse files
committed
store allocation bytes in Vec to avoid aliasing trouble
1 parent fb3e79d commit e36e63e

File tree

4 files changed

+20
-24
lines changed

4 files changed

+20
-24
lines changed

compiler/rustc_const_eval/src/interpret/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
555555

556556
type AllocExtra = ();
557557
type FrameExtra = ();
558-
type Bytes = Box<[u8]>;
558+
type Bytes = Vec<u8>;
559559

560560
#[inline(always)]
561561
fn ignore_optional_overflow_checks(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {

compiler/rustc_const_eval/src/interpret/memory.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
123123
/// A reference to some allocation that was already bounds-checked for the given region
124124
/// and had the on-access machine hooks run.
125125
#[derive(Copy, Clone)]
126-
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
126+
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Vec<u8>> {
127127
alloc: &'a Allocation<Prov, Extra, Bytes>,
128128
range: AllocRange,
129129
tcx: TyCtxt<'tcx>,
130130
alloc_id: AllocId,
131131
}
132132
/// A reference to some allocation that was already bounds-checked for the given region
133133
/// and had the on-access machine hooks run.
134-
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
134+
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Vec<u8>> {
135135
alloc: &'a mut Allocation<Prov, Extra, Bytes>,
136136
range: AllocRange,
137137
tcx: TyCtxt<'tcx>,

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

+16-20
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,29 @@ pub trait AllocBytes:
3838
/// Returns `None` if we ran out of memory on the host.
3939
fn zeroed(size: Size, _align: Align) -> Option<Self>;
4040

41-
/// Gives direct access to the raw underlying storage. Must be aligned according to the `align`
42-
/// passed during construction.
41+
/// Gives direct access to the raw underlying storage.
4342
///
44-
/// Crucially this pointer will *not* be invalidated by `deref`/`deref_mut` calls!
45-
/// In Tree Borrows terms, this pointer is a parent of the references returned there.
46-
fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8;
43+
/// Crucially this pointer is compatible with:
44+
/// - other pointers retunred by this method, and
45+
/// - references returned from `deref()`, as long as there was no write.
46+
fn as_mut_ptr(&mut self) -> *mut u8;
4747
}
4848

49-
// Default `bytes` for `Allocation` is a `Box<[u8]>`.
50-
impl AllocBytes for Box<[u8]> {
49+
// Default `bytes` for `Allocation` is a `Vec<u8>`.
50+
impl AllocBytes for Vec<u8> {
5151
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
52-
Box::<[u8]>::from(slice.into())
52+
slice.into().into_owned()
5353
}
5454

5555
fn zeroed(size: Size, _align: Align) -> Option<Self> {
5656
let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?;
5757
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
5858
let bytes = unsafe { bytes.assume_init() };
59-
Some(bytes)
59+
Some(bytes.into())
6060
}
6161

62-
fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 {
63-
// We didn't actually put the memory at the right alignment, so we can't support this.
64-
// (That's okay, this function is only needed in Miri which implements this trait for its
65-
// own type.)
66-
panic!("raw bytes access not supported");
62+
fn as_mut_ptr(&mut self) -> *mut u8 {
63+
Vec::as_mut_ptr(self)
6764
}
6865
}
6966

@@ -76,7 +73,7 @@ impl AllocBytes for Box<[u8]> {
7673
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
7774
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
7875
#[derive(HashStable)]
79-
pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box<[u8]>> {
76+
pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Vec<u8>> {
8077
/// The actual bytes of the allocation.
8178
/// Note that the bytes of a pointer represent the offset of the pointer.
8279
bytes: Bytes,
@@ -491,19 +488,18 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
491488
self.provenance.clear(range, cx)?;
492489

493490
assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check
494-
// FIXME: actually now that `self.bytes` is a `Box`, this *does* invalidate existing
495-
// immutable aliases at least under Stacked Borrows...
491+
// Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
496492
let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize());
497493
let len = range.end().bytes_usize() - range.start.bytes_usize();
498494
Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len))
499495
}
500496

501497
/// This gives direct mutable access to the entire buffer, just exposing their internal state
502-
/// without reseting anything. Directly exposes the `AllocBytes` method of the same name. Only
503-
/// works if `OFFSET_IS_ADDR` is true.
498+
/// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if
499+
/// `OFFSET_IS_ADDR` is true.
504500
pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 {
505501
assert!(Prov::OFFSET_IS_ADDR);
506-
self.bytes.get_bytes_unchecked_raw_mut()
502+
self.bytes.as_mut_ptr()
507503
}
508504
}
509505

src/tools/miri/src/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
861861

862862
type Provenance = Provenance;
863863
type ProvenanceExtra = ProvenanceExtra;
864-
type Bytes = Box<[u8]>;
864+
type Bytes = Vec<u8>;
865865

866866
type MemoryMap = MonoHashMap<
867867
AllocId,

0 commit comments

Comments
 (0)