Skip to content

Commit

Permalink
Rollup merge of rust-lang#69208 - RalfJung:debug-assert, r=Mark-Simul…
Browse files Browse the repository at this point in the history
…acrum

debug_assert a few more raw pointer methods

Fixes rust-lang#53871
  • Loading branch information
JohnTitor committed Feb 16, 2020
2 parents 2ecba06 + bec5d37 commit 1dafcce
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
9 changes: 5 additions & 4 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1423,13 +1423,14 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
}

/// Checks whether the regions of memory starting at `src` and `dst` of size
/// `count * size_of::<T>()` overlap.
fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
/// `count * size_of::<T>()` do *not* overlap.
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
let src_usize = src as usize;
let dst_usize = dst as usize;
let size = mem::size_of::<T>().checked_mul(count).unwrap();
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
size > diff
let overlaps = size > diff;
!overlaps
}

/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
Expand Down Expand Up @@ -1524,7 +1525,7 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {

debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
debug_assert!(is_nonoverlapping(src, dst, count), "attempt to copy to overlapping memory");
copy_nonoverlapping(src, dst, count)
}

Expand Down
12 changes: 11 additions & 1 deletion src/libcore/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
use crate::cmp::Ordering;
use crate::fmt;
use crate::hash;
use crate::intrinsics;
use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping};
use crate::mem::{self, MaybeUninit};

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -392,6 +392,10 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
#[inline]
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
debug_assert!(is_aligned_and_not_null(x), "attempt to swap unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(y), "attempt to swap unaligned or null pointer");
debug_assert!(is_nonoverlapping(x, y, count), "attempt to swap overlapping memory");

let x = x as *mut u8;
let y = y as *mut u8;
let len = mem::size_of::<T>() * count;
Expand Down Expand Up @@ -619,6 +623,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn read<T>(src: *const T) -> T {
// `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
tmp.assume_init()
Expand Down Expand Up @@ -712,6 +717,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
// `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
tmp.assume_init()
Expand Down Expand Up @@ -804,6 +810,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn write<T>(dst: *mut T, src: T) {
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::move_val_init(&mut *dst, src)
}

Expand Down Expand Up @@ -896,6 +903,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
// `copy_nonoverlapping` takes care of debug_assert.
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
mem::forget(src);
}
Expand Down Expand Up @@ -967,6 +975,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn read_volatile<T>(src: *const T) -> T {
debug_assert!(is_aligned_and_not_null(src), "attempt to read from unaligned or null pointer");
intrinsics::volatile_load(src)
}

Expand Down Expand Up @@ -1035,6 +1044,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::volatile_store(dst, src);
}

Expand Down

0 comments on commit 1dafcce

Please sign in to comment.