mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #131384 - saethlin:precondition-tests, r=ibraheemdev
Update precondition tests (especially for zero-size access to null) I don't much like the current way I've updated the precondition check helpers, but I couldn't come up with anything better. Ideas welcome. I've organized `tests/ui/precondition-checks` mostly with one file per function that has `assert_unsafe_precondition` in it, with revisions that check each precondition. The important new test is `tests/ui/precondition-checks/zero-size-null.rs`.
This commit is contained in:
commit
32062b4b8e
@ -506,7 +506,7 @@ impl AsciiChar {
|
||||
pub const unsafe fn digit_unchecked(d: u8) -> Self {
|
||||
assert_unsafe_precondition!(
|
||||
check_language_ub,
|
||||
"`AsciiChar::digit_unchecked` input cannot exceed 9.",
|
||||
"`ascii::Char::digit_unchecked` input cannot exceed 9.",
|
||||
(d: u8 = d) => d < 10
|
||||
);
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::marker::{DiscriminantKind, Tuple};
|
||||
use crate::mem::SizedTypeProperties;
|
||||
use crate::{ptr, ub_checks};
|
||||
|
||||
pub mod mir;
|
||||
@ -3364,10 +3365,12 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
|
||||
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)
|
||||
) => {
|
||||
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
|
||||
@ -3465,9 +3468,10 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
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)
|
||||
}
|
||||
@ -3544,7 +3548,8 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
||||
(
|
||||
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 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
|
||||
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)
|
||||
) => {
|
||||
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
|
||||
@ -1278,7 +1280,8 @@ pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
|
||||
(
|
||||
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)
|
||||
}
|
||||
@ -1430,7 +1433,8 @@ pub const unsafe fn read<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)
|
||||
);
|
||||
crate::intrinsics::read_via_copy(src)
|
||||
}
|
||||
@ -1635,7 +1639,8 @@ pub const unsafe fn write<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::write_via_move(dst, src)
|
||||
}
|
||||
@ -1808,7 +1813,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)
|
||||
}
|
||||
@ -1887,7 +1893,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 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
|
||||
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 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m
|
||||
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)
|
||||
|
@ -109,15 +109,15 @@ pub(crate) const fn check_language_ub() -> bool {
|
||||
intrinsics::ub_checks() && const_eval_select((), comptime, runtime)
|
||||
}
|
||||
|
||||
/// Checks whether `ptr` is properly aligned with respect to
|
||||
/// `align_of::<T>()`.
|
||||
/// Checks whether `ptr` is properly aligned with respect to the given alignment, and
|
||||
/// if `is_zst == false`, that `ptr` is not null.
|
||||
///
|
||||
/// In `const` this is approximate and can fail spuriously. It is primarily intended
|
||||
/// 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 {
|
||||
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
11
tests/ui/precondition-checks/alignment.rs
Normal file
11
tests/ui/precondition-checks/alignment.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: Alignment::new_unchecked requires
|
||||
|
||||
#![feature(ptr_alignment_type)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::ptr::Alignment::new_unchecked(0);
|
||||
}
|
||||
}
|
11
tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
Normal file
11
tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: `ascii::Char::digit_unchecked` input cannot exceed 9
|
||||
|
||||
#![feature(ascii_char)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::ascii::Char::digit_unchecked(b'a');
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/assert_unchecked.rs
Normal file
9
tests/ui/precondition-checks/assert_unchecked.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked must never be called when the condition is false
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::hint::assert_unchecked(false);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/char-from_u32_unchecked.rs
Normal file
9
tests/ui/precondition-checks/char-from_u32_unchecked.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: invalid value for `char`
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
char::from_u32_unchecked(0xD801);
|
||||
}
|
||||
}
|
25
tests/ui/precondition-checks/copy-nonoverlapping.rs
Normal file
25
tests/ui/precondition-checks/copy-nonoverlapping.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
|
||||
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let src = [0u16; 3];
|
||||
let mut dst = [0u16; 3];
|
||||
let src = src.as_ptr();
|
||||
let dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null_src)]
|
||||
ptr::copy_nonoverlapping(ptr::null(), dst, 1);
|
||||
#[cfg(null_dst)]
|
||||
ptr::copy_nonoverlapping(src, ptr::null_mut(), 1);
|
||||
#[cfg(misaligned_src)]
|
||||
ptr::copy_nonoverlapping(src.byte_add(1), dst, 1);
|
||||
#[cfg(misaligned_dst)]
|
||||
ptr::copy_nonoverlapping(src, dst.byte_add(1), 1);
|
||||
#[cfg(overlapping)]
|
||||
ptr::copy_nonoverlapping(dst, dst.add(1), 2);
|
||||
}
|
||||
}
|
23
tests/ui/precondition-checks/copy.rs
Normal file
23
tests/ui/precondition-checks/copy.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
|
||||
//@ revisions: null_src null_dst misaligned_src misaligned_dst
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let src = [0u16; 3];
|
||||
let mut dst = [0u16; 3];
|
||||
let src = src.as_ptr();
|
||||
let dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null_src)]
|
||||
ptr::copy(ptr::null(), dst, 1);
|
||||
#[cfg(null_dst)]
|
||||
ptr::copy(src, ptr::null_mut(), 1);
|
||||
#[cfg(misaligned_src)]
|
||||
ptr::copy(src.byte_add(1), dst, 1);
|
||||
#[cfg(misaligned_dst)]
|
||||
ptr::copy(src, dst.byte_add(1), 1);
|
||||
}
|
||||
}
|
15
tests/ui/precondition-checks/layout.rs
Normal file
15
tests/ui/precondition-checks/layout.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires
|
||||
//@ revisions: toolarge badalign
|
||||
//@[toolarge] compile-flags: --cfg toolarge
|
||||
//@[badalign] compile-flags: --cfg badalign
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
#[cfg(toolarge)]
|
||||
std::alloc::Layout::from_size_align_unchecked(isize::MAX as usize, 2);
|
||||
#[cfg(badalign)]
|
||||
std::alloc::Layout::from_size_align_unchecked(1, 3);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
|
||||
//@ ignore-debug
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/nonnull.rs
Normal file
9
tests/ui/precondition-checks/nonnull.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: NonNull::new_unchecked requires
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::ptr::NonNull::new_unchecked(std::ptr::null_mut::<u8>());
|
||||
}
|
||||
}
|
12
tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
Normal file
12
tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: NonZero::from_mut_unchecked requires
|
||||
|
||||
#![feature(nonzero_from_mut)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut num = 0u8;
|
||||
std::num::NonZeroU8::from_mut_unchecked(&mut num);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/nonzero-new_unchecked.rs
Normal file
9
tests/ui/precondition-checks/nonzero-new_unchecked.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: NonZero::new_unchecked requires
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::num::NonZeroU8::new_unchecked(0);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
|
||||
//@ ignore-debug
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: slice::get_unchecked requires
|
||||
//@ ignore-debug
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let sli: &[u8] = &[0];
|
||||
sli.get_unchecked(1);
|
||||
}
|
||||
}
|
18
tests/ui/precondition-checks/read.rs
Normal file
18
tests/ui/precondition-checks/read.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::read requires
|
||||
//@ revisions: null misaligned
|
||||
//@ ignore-test
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let src = [0u16; 2];
|
||||
let src = src.as_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::read(ptr::null::<u8>());
|
||||
#[cfg(misaligned)]
|
||||
ptr::read(src.byte_add(1));
|
||||
}
|
||||
}
|
17
tests/ui/precondition-checks/read_volatile.rs
Normal file
17
tests/ui/precondition-checks/read_volatile.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
|
||||
//@ revisions: null misaligned
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let src = [0u16; 2];
|
||||
let src = src.as_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::read_volatile(ptr::null::<u8>());
|
||||
#[cfg(misaligned)]
|
||||
ptr::read_volatile(src.byte_add(1));
|
||||
}
|
||||
}
|
17
tests/ui/precondition-checks/replace.rs
Normal file
17
tests/ui/precondition-checks/replace.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
|
||||
//@ revisions: null misaligned
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let mut dst = [0u16; 2];
|
||||
let dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::replace(ptr::null_mut::<u8>(), 1);
|
||||
#[cfg(misaligned)]
|
||||
ptr::replace(dst.byte_add(1), 1u16);
|
||||
}
|
||||
}
|
16
tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
Normal file
16
tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
|
||||
//@ revisions: null misaligned toolarge
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
let _s: &mut [u8] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
|
||||
#[cfg(misaligned)]
|
||||
let _s: &mut [u16] = std::slice::from_raw_parts_mut(1usize as *mut u16, 0);
|
||||
#[cfg(toolarge)]
|
||||
let _s: &mut [u16] =
|
||||
std::slice::from_raw_parts_mut(2usize as *mut u16, isize::MAX as usize);
|
||||
}
|
||||
}
|
15
tests/ui/precondition-checks/slice-from-raw-parts.rs
Normal file
15
tests/ui/precondition-checks/slice-from-raw-parts.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
|
||||
//@ revisions: null misaligned toolarge
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0);
|
||||
#[cfg(misaligned)]
|
||||
let _s: &[u16] = std::slice::from_raw_parts(1usize as *const u16, 0);
|
||||
#[cfg(toolarge)]
|
||||
let _s: &[u16] = std::slice::from_raw_parts(2usize as *const u16, isize::MAX as usize);
|
||||
}
|
||||
}
|
20
tests/ui/precondition-checks/slice-get_unchecked.rs
Normal file
20
tests/ui/precondition-checks/slice-get_unchecked.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked requires
|
||||
//@ revisions: usize range range_to range_from backwards_range
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let s = &[0];
|
||||
#[cfg(usize)]
|
||||
s.get_unchecked(1);
|
||||
#[cfg(range)]
|
||||
s.get_unchecked(1..2);
|
||||
#[cfg(range_to)]
|
||||
s.get_unchecked(..2);
|
||||
#[cfg(range_from)]
|
||||
s.get_unchecked(2..);
|
||||
#[cfg(backwards_range)]
|
||||
s.get_unchecked(1..0);
|
||||
}
|
||||
}
|
20
tests/ui/precondition-checks/slice-get_unchecked_mut.rs
Normal file
20
tests/ui/precondition-checks/slice-get_unchecked_mut.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked_mut requires
|
||||
//@ revisions: usize range range_to range_from backwards_range
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut s = &mut [0];
|
||||
#[cfg(usize)]
|
||||
s.get_unchecked_mut(1);
|
||||
#[cfg(range)]
|
||||
s.get_unchecked_mut(1..2);
|
||||
#[cfg(range_to)]
|
||||
s.get_unchecked_mut(..2);
|
||||
#[cfg(range_from)]
|
||||
s.get_unchecked_mut(2..);
|
||||
#[cfg(backwards_range)]
|
||||
s.get_unchecked_mut(1..0);
|
||||
}
|
||||
}
|
14
tests/ui/precondition-checks/slice-swap_unchecked.rs
Normal file
14
tests/ui/precondition-checks/slice-swap_unchecked.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: index out of bounds: the len is 2 but the index is 2
|
||||
//@ revisions: oob_a oob_b
|
||||
|
||||
fn main() {
|
||||
let mut pair = [0u8; 2];
|
||||
unsafe {
|
||||
#[cfg(oob_a)]
|
||||
pair.swap(0, 2);
|
||||
#[cfg(oob_b)]
|
||||
pair.swap(2, 0);
|
||||
}
|
||||
}
|
18
tests/ui/precondition-checks/str-get_unchecked.rs
Normal file
18
tests/ui/precondition-checks/str-get_unchecked.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked requires
|
||||
//@ revisions: range range_to range_from backwards_range
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let s = "💅";
|
||||
#[cfg(range)]
|
||||
s.get_unchecked(4..5);
|
||||
#[cfg(range_to)]
|
||||
s.get_unchecked(..5);
|
||||
#[cfg(range_from)]
|
||||
s.get_unchecked(5..);
|
||||
#[cfg(backwards_range)]
|
||||
s.get_unchecked(1..0);
|
||||
}
|
||||
}
|
19
tests/ui/precondition-checks/str-get_unchecked_mut.rs
Normal file
19
tests/ui/precondition-checks/str-get_unchecked_mut.rs
Normal file
@ -0,0 +1,19 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked_mut requires
|
||||
//@ revisions: range range_to range_from backwards_range
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut s: String = "💅".chars().collect();
|
||||
let mut s: &mut str = &mut s;
|
||||
#[cfg(range)]
|
||||
s.get_unchecked_mut(4..5);
|
||||
#[cfg(range_to)]
|
||||
s.get_unchecked_mut(..5);
|
||||
#[cfg(range_from)]
|
||||
s.get_unchecked_mut(5..);
|
||||
#[cfg(backwards_range)]
|
||||
s.get_unchecked_mut(1..0);
|
||||
}
|
||||
}
|
25
tests/ui/precondition-checks/swap-nonoverlapping.rs
Normal file
25
tests/ui/precondition-checks/swap-nonoverlapping.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
|
||||
//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let mut src = [0u16; 3];
|
||||
let mut dst = [0u16; 3];
|
||||
let src = src.as_mut_ptr();
|
||||
let dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null_src)]
|
||||
ptr::swap_nonoverlapping(ptr::null_mut(), dst, 1);
|
||||
#[cfg(null_dst)]
|
||||
ptr::swap_nonoverlapping(src, ptr::null_mut(), 1);
|
||||
#[cfg(misaligned_src)]
|
||||
ptr::swap_nonoverlapping(src.byte_add(1), dst, 1);
|
||||
#[cfg(misaligned_dst)]
|
||||
ptr::swap_nonoverlapping(src, dst.byte_add(1), 1);
|
||||
#[cfg(overlapping)]
|
||||
ptr::swap_nonoverlapping(dst, dst.add(1), 2);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/unchecked_add.rs
Normal file
9
tests/ui/precondition-checks/unchecked_add.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
1u8.unchecked_add(u8::MAX);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/unchecked_mul.rs
Normal file
9
tests/ui/precondition-checks/unchecked_mul.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
2u8.unchecked_add(u8::MAX);
|
||||
}
|
||||
}
|
11
tests/ui/precondition-checks/unchecked_shl.rs
Normal file
11
tests/ui/precondition-checks/unchecked_shl.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow
|
||||
|
||||
#![feature(unchecked_shifts)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
0u8.unchecked_shl(u8::BITS);
|
||||
}
|
||||
}
|
11
tests/ui/precondition-checks/unchecked_shr.rs
Normal file
11
tests/ui/precondition-checks/unchecked_shr.rs
Normal file
@ -0,0 +1,11 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow
|
||||
|
||||
#![feature(unchecked_shifts)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
0u8.unchecked_shr(u8::BITS);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/unchecked_sub.rs
Normal file
9
tests/ui/precondition-checks/unchecked_sub.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_sub cannot overflow
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
0u8.unchecked_sub(1u8);
|
||||
}
|
||||
}
|
9
tests/ui/precondition-checks/unreachable_unchecked.rs
Normal file
9
tests/ui/precondition-checks/unreachable_unchecked.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::hint::unreachable_unchecked();
|
||||
}
|
||||
}
|
18
tests/ui/precondition-checks/write.rs
Normal file
18
tests/ui/precondition-checks/write.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
|
||||
//@ revisions: null misaligned
|
||||
//@ ignore-test
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let mut dst = [0u16; 2];
|
||||
let mut dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::write(ptr::null_mut::<u8>(), 1u8);
|
||||
#[cfg(misaligned)]
|
||||
ptr::write(dst.byte_add(1), 1u16);
|
||||
}
|
||||
}
|
18
tests/ui/precondition-checks/write_bytes.rs
Normal file
18
tests/ui/precondition-checks/write_bytes.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
|
||||
//@ revisions: null misaligned
|
||||
//@ ignore-test
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let mut dst = [0u16; 2];
|
||||
let mut dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::write_bytes(ptr::null_mut::<u8>(), 1u8, 2);
|
||||
#[cfg(misaligned)]
|
||||
ptr::write_bytes(dst.byte_add(1), 1u8, 2);
|
||||
}
|
||||
}
|
17
tests/ui/precondition-checks/write_volatile.rs
Normal file
17
tests/ui/precondition-checks/write_volatile.rs
Normal file
@ -0,0 +1,17 @@
|
||||
//@ run-fail
|
||||
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
|
||||
//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
|
||||
//@ revisions: null misaligned
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
let mut dst = [0u16; 2];
|
||||
let mut dst = dst.as_mut_ptr();
|
||||
unsafe {
|
||||
#[cfg(null)]
|
||||
ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
|
||||
#[cfg(misaligned)]
|
||||
ptr::write_volatile(dst.byte_add(1), 1u16);
|
||||
}
|
||||
}
|
21
tests/ui/precondition-checks/zero-size-null.rs
Normal file
21
tests/ui/precondition-checks/zero-size-null.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Test that none of the precondition checks panic on zero-sized reads or writes through null.
|
||||
|
||||
//@ run-pass
|
||||
//@ compile-flags: -Zmir-opt-level=0 -Copt-level=0 -Cdebug-assertions=yes
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping::<u8>(ptr::null(), ptr::null_mut(), 0);
|
||||
ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123);
|
||||
ptr::copy::<u8>(ptr::null(), ptr::null_mut(), 0);
|
||||
ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123);
|
||||
ptr::swap::<()>(ptr::null_mut(), ptr::null_mut());
|
||||
ptr::replace::<()>(ptr::null_mut(), ());
|
||||
ptr::read::<()>(ptr::null());
|
||||
ptr::write::<()>(ptr::null_mut(), ());
|
||||
ptr::read_volatile::<()>(ptr::null());
|
||||
ptr::write_volatile::<()>(ptr::null_mut(), ());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user