Rollup merge of #78602 - RalfJung:raw-ptr-aliasing-issues, r=m-ou-se

fix various aliasing issues in the standard library

This fixes various cases where the standard library either used raw pointers after they were already invalidated by using the original reference again, or created raw pointers for one element of a slice and used it to access neighboring elements.
This commit is contained in:
Mara Bos 2020-11-01 11:53:36 +01:00 committed by GitHub
commit 8ed31d2782
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 17 additions and 9 deletions

View File

@ -1036,8 +1036,9 @@ unsafe fn move_to(&mut self, index: usize) {
debug_assert!(index != self.pos);
debug_assert!(index < self.data.len());
unsafe {
let index_ptr: *const _ = self.data.get_unchecked(index);
let hole_ptr = self.data.get_unchecked_mut(self.pos);
let ptr = self.data.as_mut_ptr();
let index_ptr: *const _ = ptr.add(index);
let hole_ptr = ptr.add(self.pos);
ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
}
self.pos = index;

View File

@ -595,7 +595,6 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
let mut curr = buf.len() as isize;
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
let (n, rem) = udiv_1e19(n);
parse_u64_into(rem, &mut buf, &mut curr);
@ -606,7 +605,11 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
// SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
// remaining since it has length 39
unsafe {
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
ptr::write_bytes(
MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target),
b'0',
(curr - target) as usize,
);
}
curr = target;
@ -615,6 +618,9 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
// Should this following branch be annotated with unlikely?
if n != 0 {
let target = (buf.len() - 38) as isize;
// The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
// buf `buf` is not used in this scope so we are good.
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
// SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
// There can only be at most 1 digit remaining.
unsafe {
@ -629,7 +635,7 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
// UTF-8 since `DEC_DIGITS_LUT` is
let buf_slice = unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(
buf_ptr.offset(curr),
MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr),
buf.len() - curr as usize,
))
};

View File

@ -111,7 +111,7 @@ macro_rules! load_int_le {
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
let mut data = 0 as $int_ty;
ptr::copy_nonoverlapping(
$buf.get_unchecked($i),
$buf.as_ptr().add($i),
&mut data as *mut _ as *mut u8,
mem::size_of::<$int_ty>(),
);

View File

@ -842,13 +842,13 @@ pub unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
this as *const [MaybeUninit<T>] as *const T
this.as_ptr() as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
this as *mut [MaybeUninit<T>] as *mut T
this.as_mut_ptr() as *mut T
}
}

View File

@ -178,7 +178,8 @@ pub fn sleep(dur: Duration) {
tv_nsec: nsecs,
};
secs -= ts.tv_sec as u64;
if libc::nanosleep(&ts, &mut ts) == -1 {
let ts_ptr = &mut ts as *mut _;
if libc::nanosleep(ts_ptr, ts_ptr) == -1 {
assert_eq!(os::errno(), libc::EINTR);
secs += ts.tv_sec as u64;
nsecs = ts.tv_nsec;