Skip to content

Commit 365b90c

Browse files
committed
refactor memory access methods a bit
1 parent 1d498d5 commit 365b90c

File tree

1 file changed

+47
-40
lines changed

1 file changed

+47
-40
lines changed

src/librustc_mir/interpret/memory.rs

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
287287

288288
/// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
289289
/// of an allocation (i.e., at the first *inaccessible* location) *is* considered
290-
/// in-bounds! This follows C's/LLVM's rules.
290+
/// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used
291+
/// for the error message.
292+
/// If you want to check bounds before doing a memory access, be sure to
293+
/// check the pointer one past the end of your access, then everything will
294+
/// work out exactly.
291295
pub fn check_bounds(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> {
292296
let alloc = self.get(ptr.alloc_id)?;
293297
let allocation_size = alloc.bytes.len() as u64;
@@ -498,70 +502,71 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
498502

499503
/// Byte accessors
500504
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
501-
/// This checks alignment!
502-
fn get_bytes_unchecked(
505+
/// The last argument controls whether we error out when there are undefined
506+
/// or pointer bytes. You should never call this, call `get_bytes` or
507+
/// `get_bytes_unchecked` instead,
508+
fn get_bytes_internal(
503509
&self,
504510
ptr: Pointer,
505511
size: Size,
506512
align: Align,
513+
check_defined_and_ptr: bool,
507514
) -> EvalResult<'tcx, &[u8]> {
508-
// Zero-sized accesses can use dangling pointers,
509-
// but they still have to be aligned and non-NULL
515+
assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
510516
self.check_align(ptr.into(), align)?;
511-
if size.bytes() == 0 {
512-
return Ok(&[]);
513-
}
514517
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
515-
self.check_bounds(ptr.offset(size, self)?, true)?;
518+
self.check_bounds(ptr.offset(size, &*self)?, true)?;
519+
520+
if check_defined_and_ptr {
521+
self.check_defined(ptr, size)?;
522+
if self.relocations(ptr, size)?.len() != 0 {
523+
return err!(ReadPointerAsBytes);
524+
}
525+
}
526+
516527
let alloc = self.get(ptr.alloc_id)?;
517528
assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
518529
assert_eq!(size.bytes() as usize as u64, size.bytes());
519530
let offset = ptr.offset.bytes() as usize;
520531
Ok(&alloc.bytes[offset..offset + size.bytes() as usize])
521532
}
522533

523-
/// This checks alignment!
524-
fn get_bytes_unchecked_mut(
534+
#[inline]
535+
fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
536+
self.get_bytes_internal(ptr, size, align, true)
537+
}
538+
539+
/// It is the caller's responsibility to handle undefined and pointer bytes.
540+
#[inline]
541+
fn get_bytes_with_undef_and_ptr(
542+
&self,
543+
ptr: Pointer,
544+
size: Size,
545+
align: Align
546+
) -> EvalResult<'tcx, &[u8]> {
547+
self.get_bytes_internal(ptr, size, align, false)
548+
}
549+
550+
fn get_bytes_mut(
525551
&mut self,
526552
ptr: Pointer,
527553
size: Size,
528554
align: Align,
529555
) -> EvalResult<'tcx, &mut [u8]> {
530-
// Zero-sized accesses can use dangling pointers,
531-
// but they still have to be aligned and non-NULL
556+
assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`");
532557
self.check_align(ptr.into(), align)?;
533-
if size.bytes() == 0 {
534-
return Ok(&mut []);
535-
}
536558
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
537-
self.check_bounds(ptr.offset(size, &*self)?, true)?;
559+
self.check_bounds(ptr.offset(size, &self)?, true)?;
560+
561+
self.mark_definedness(ptr, size, true)?;
562+
self.clear_relocations(ptr, size)?;
563+
538564
let alloc = self.get_mut(ptr.alloc_id)?;
539565
assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
540566
assert_eq!(size.bytes() as usize as u64, size.bytes());
541567
let offset = ptr.offset.bytes() as usize;
542568
Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize])
543569
}
544-
545-
fn get_bytes(&self, ptr: Pointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
546-
assert_ne!(size.bytes(), 0);
547-
if self.relocations(ptr, size)?.len() != 0 {
548-
return err!(ReadPointerAsBytes);
549-
}
550-
self.check_defined(ptr, size)?;
551-
self.get_bytes_unchecked(ptr, size, align)
552-
}
553-
554-
fn get_bytes_mut(
555-
&mut self,
556-
ptr: Pointer,
557-
size: Size,
558-
align: Align,
559-
) -> EvalResult<'tcx, &mut [u8]> {
560-
assert_ne!(size.bytes(), 0);
561-
self.clear_relocations(ptr, size)?;
562-
self.mark_definedness(ptr, size, true)?;
563-
self.get_bytes_unchecked_mut(ptr, size, align)
564-
}
565570
}
566571

567572
/// Reading and writing
@@ -672,7 +677,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
672677
};
673678

674679
// This also checks alignment.
675-
let src_bytes = self.get_bytes_unchecked(src, size, src_align)?.as_ptr();
680+
let src_bytes = self.get_bytes_with_undef_and_ptr(src, size, src_align)?.as_ptr();
676681
let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr();
677682

678683
// SAFE: The above indexing would have panicked if there weren't at least `size` bytes
@@ -775,7 +780,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
775780
// Make sure we don't read part of a pointer as a pointer
776781
self.check_relocation_edges(ptr, size)?;
777782
// get_bytes_unchecked tests alignment
778-
let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?;
783+
let bytes = self.get_bytes_with_undef_and_ptr(
784+
ptr, size, ptr_align.min(self.int_align(size))
785+
)?;
779786
// Undef check happens *after* we established that the alignment is correct.
780787
// We must not return Ok() for unaligned pointers!
781788
if !self.is_defined(ptr, size)? {

0 commit comments

Comments
 (0)