diff options
Diffstat (limited to 'src/test/ui/const-ptr/forbidden_slices.rs')
-rw-r--r-- | src/test/ui/const-ptr/forbidden_slices.rs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/test/ui/const-ptr/forbidden_slices.rs b/src/test/ui/const-ptr/forbidden_slices.rs new file mode 100644 index 000000000..e2184911f --- /dev/null +++ b/src/test/ui/const-ptr/forbidden_slices.rs @@ -0,0 +1,98 @@ +// stderr-per-bitwidth +// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID" +// normalize-stderr-test "a[0-9]+\+0x" -> "A_ID+0x" +// error-pattern: could not evaluate static initializer +#![feature( + slice_from_ptr_range, + const_slice_from_ptr_range, + pointer_byte_offsets, + const_pointer_byte_offsets +)] +use std::{ + mem::{size_of, MaybeUninit}, + ptr, + slice::{from_ptr_range, from_raw_parts}, +}; + +// Null is never valid for reads +pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) }; +pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) }; + +// Out of bounds +pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) }; + +// Reading uninitialized data +pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; //~ ERROR: it is undefined behavior to use this value +// Reinterpret pointers as integers (UB in CTFE.) +pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; //~ ERROR: it is undefined behavior to use this value +// Layout mismatch +pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; //~ ERROR: it is undefined behavior to use this value + +// Reading padding is not ok +pub static S7: &[u16] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D2 as *const Struct as *const u16).byte_add(1); + + from_raw_parts(ptr, 4) +}; + +// Unaligned read +pub static S8: &[u64] = unsafe { + let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>(); + + from_raw_parts(ptr, 1) +}; + +pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; +pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; +pub static R2: &[u32] = unsafe { + let ptr = &D0 as *const u32; + from_ptr_range(ptr..ptr.add(2)) +}; +pub static R4: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8; + from_ptr_range(ptr..ptr.add(1)) +}; +pub static R5: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D3 as *const &u32; + from_ptr_range(ptr.cast()..ptr.add(1).cast()) +}; +pub static R6: &[bool] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D0 as *const u32 as *const bool; + from_ptr_range(ptr..ptr.add(4)) +}; +pub static R7: &[u16] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D2 as *const Struct as *const u16).byte_add(1); + from_ptr_range(ptr..ptr.add(4)) +}; +pub static R8: &[u64] = unsafe { + let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::<u64>(); + from_ptr_range(ptr..ptr.add(1)) +}; + +// This is sneaky: &D0 and &D0 point to different objects +// (even if at runtime they have the same address) +pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) }; +pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) }; + +const D0: u32 = 0x11; +const D1: MaybeUninit<&u32> = MaybeUninit::uninit(); +const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 }; +const D3: &u32 = &42; +const D4: [u32; 2] = [17, 42]; + +#[repr(C)] +struct Struct { + a: u8, + // _pad: [MaybeUninit<u8>; 3] + b: u32, + c: u16, + d: u8, + // _pad: [MaybeUninit<u8>; 1] +} + +fn main() {} |