Allow zero-size reads/writes on null pointers
This commit is contained in:
parent
eb4e234674
commit
0c41c3414c
@ -64,6 +64,7 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::marker::{DiscriminantKind, Tuple};
|
||||
use crate::mem::SizedTypeProperties;
|
||||
use crate::{ptr, ub_checks};
|
||||
|
||||
pub mod mir;
|
||||
@ -3311,10 +3312,12 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
|
||||
size: usize = size_of::<T>(),
|
||||
align: usize = align_of::<T>(),
|
||||
count: usize = count,
|
||||
) =>
|
||||
ub_checks::is_aligned_and_not_null(src, align)
|
||||
&& ub_checks::is_aligned_and_not_null(dst, align)
|
||||
&& ub_checks::is_nonoverlapping(src, dst, size, count)
|
||||
) => {
|
||||
let zero_size = count == 0 || size == 0;
|
||||
ub_checks::is_aligned_and_not_null(src, align, zero_size)
|
||||
&& ub_checks::is_aligned_and_not_null(dst, align, zero_size)
|
||||
&& ub_checks::is_nonoverlapping(src, dst, size, count)
|
||||
}
|
||||
);
|
||||
|
||||
// SAFETY: the safety contract for `copy_nonoverlapping` must be
|
||||
@ -3412,9 +3415,10 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
|
||||
src: *const () = src as *const (),
|
||||
dst: *mut () = dst as *mut (),
|
||||
align: usize = align_of::<T>(),
|
||||
zero_size: bool = T::IS_ZST || count == 0,
|
||||
) =>
|
||||
ub_checks::is_aligned_and_not_null(src, align)
|
||||
&& ub_checks::is_aligned_and_not_null(dst, align)
|
||||
ub_checks::is_aligned_and_not_null(src, align, zero_size)
|
||||
&& ub_checks::is_aligned_and_not_null(dst, align, zero_size)
|
||||
);
|
||||
copy(src, dst, count)
|
||||
}
|
||||
@ -3491,7 +3495,8 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
|
||||
(
|
||||
addr: *const () = dst as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align)
|
||||
zero_size: bool = T::IS_ZST || count == 0,
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align, zero_size)
|
||||
);
|
||||
write_bytes(dst, val, count)
|
||||
}
|
||||
|
@ -448,7 +448,7 @@
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::marker::FnPtr;
|
||||
use crate::mem::{self, MaybeUninit};
|
||||
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
||||
use crate::{fmt, hash, intrinsics, ub_checks};
|
||||
|
||||
mod alignment;
|
||||
@ -1165,10 +1165,12 @@ macro_rules! attempt_swap_as_chunks {
|
||||
size: usize = size_of::<T>(),
|
||||
align: usize = align_of::<T>(),
|
||||
count: usize = count,
|
||||
) =>
|
||||
ub_checks::is_aligned_and_not_null(x, align)
|
||||
&& ub_checks::is_aligned_and_not_null(y, align)
|
||||
&& ub_checks::is_nonoverlapping(x, y, size, count)
|
||||
) => {
|
||||
let zero_size = size == 0 || count == 0;
|
||||
ub_checks::is_aligned_and_not_null(x, align, zero_size)
|
||||
&& ub_checks::is_aligned_and_not_null(y, align, zero_size)
|
||||
&& ub_checks::is_nonoverlapping(x, y, size, count)
|
||||
}
|
||||
);
|
||||
|
||||
// Split up the slice into small power-of-two-sized chunks that LLVM is able
|
||||
@ -1277,7 +1279,8 @@ macro_rules! attempt_swap_as_chunks {
|
||||
(
|
||||
addr: *const () = dst as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align)
|
||||
is_zst: bool = T::IS_ZST,
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align, is_zst)
|
||||
);
|
||||
mem::replace(&mut *dst, src)
|
||||
}
|
||||
@ -1806,7 +1809,8 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
|
||||
(
|
||||
addr: *const () = src as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align)
|
||||
is_zst: bool = T::IS_ZST,
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align, is_zst)
|
||||
);
|
||||
intrinsics::volatile_load(src)
|
||||
}
|
||||
@ -1885,7 +1889,8 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||
(
|
||||
addr: *mut () = dst as *mut (),
|
||||
align: usize = align_of::<T>(),
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align)
|
||||
is_zst: bool = T::IS_ZST,
|
||||
) => ub_checks::is_aligned_and_not_null(addr, align, is_zst)
|
||||
);
|
||||
intrinsics::volatile_store(dst, src);
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
||||
align: usize = align_of::<T>(),
|
||||
len: usize = len,
|
||||
) =>
|
||||
ub_checks::is_aligned_and_not_null(data, align)
|
||||
ub_checks::is_aligned_and_not_null(data, align, false)
|
||||
&& ub_checks::is_valid_allocation_size(size, len)
|
||||
);
|
||||
&*ptr::slice_from_raw_parts(data, len)
|
||||
@ -187,7 +187,7 @@
|
||||
align: usize = align_of::<T>(),
|
||||
len: usize = len,
|
||||
) =>
|
||||
ub_checks::is_aligned_and_not_null(data, align)
|
||||
ub_checks::is_aligned_and_not_null(data, align, false)
|
||||
&& ub_checks::is_valid_allocation_size(size, len)
|
||||
);
|
||||
&mut *ptr::slice_from_raw_parts_mut(data, len)
|
||||
|
@ -116,8 +116,8 @@ const fn comptime() -> bool {
|
||||
/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
|
||||
/// check is anyway not executed in `const`.
|
||||
#[inline]
|
||||
pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool {
|
||||
!ptr.is_null() && ptr.is_aligned_to(align)
|
||||
pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool {
|
||||
if is_zst { ptr.is_aligned_to(align) } else { !ptr.is_null() && ptr.is_aligned_to(align) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
Loading…
Reference in New Issue
Block a user