diff options
Diffstat (limited to 'src/test/ui/intrinsics/panic-uninitialized-zeroed.rs')
-rw-r--r-- | src/test/ui/intrinsics/panic-uninitialized-zeroed.rs | 253 |
1 files changed, 169 insertions, 84 deletions
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 255151a96..ec3860a32 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,6 +1,5 @@ // run-pass // needs-unwind -// ignore-wasm32-bare compiled with panic=abort by default // revisions: mir thir strict // [thir]compile-flags: -Zthir-unsafeck // [strict]compile-flags: -Zstrict-init-checks @@ -8,7 +7,7 @@ // This test checks panic emitted from `mem::{uninitialized,zeroed}`. -#![feature(never_type, arbitrary_enum_discriminant)] +#![feature(never_type)] #![allow(deprecated, invalid_value)] use std::{ @@ -35,6 +34,12 @@ enum OneVariant_NonZero { DeadVariant(Bar), } +#[allow(dead_code, non_camel_case_types)] +enum OneVariant_Ref { + Variant(&'static i32), + DeadVariant(Bar), +} + // An `Aggregate` abi enum where 0 is not a valid discriminant. #[allow(dead_code)] #[repr(i32)] @@ -64,6 +69,7 @@ enum ZeroIsValid { One(NonNull<()>) = 1, } +#[track_caller] fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { let err = panic::catch_unwind(op).err(); assert_eq!( @@ -72,6 +78,15 @@ fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { ); } +#[track_caller] +fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { + let err = panic::catch_unwind(op).err(); + assert_eq!( + err.as_ref().and_then(|a| a.downcast_ref::<&str>()), + if cfg!(strict) { Some(&msg) } else { None }, + ); +} + fn main() { unsafe { // Uninhabited types @@ -140,92 +155,216 @@ fn main() { "attempted to instantiate uninhabited type `[Bar; 2]`" ); - // Types that do not like zero-initialziation + // Types that don't allow either. test_panic_msg( - || mem::uninitialized::<fn()>(), - "attempted to leave type `fn()` uninitialized, which is invalid" + || mem::zeroed::<&i32>(), + "attempted to zero-initialize type `&i32`, which is invalid" ); test_panic_msg( - || mem::zeroed::<fn()>(), - "attempted to zero-initialize type `fn()`, which is invalid" + || mem::uninitialized::<&i32>(), + "attempted to leave type `&i32` uninitialized, which is invalid" ); test_panic_msg( - || mem::uninitialized::<*const dyn Send>(), - "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid" + || mem::zeroed::<Box<[i32; 0]>>(), + "attempted to zero-initialize type `alloc::boxed::Box<[i32; 0]>`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<Box<[i32; 0]>>(), + "attempted to leave type `alloc::boxed::Box<[i32; 0]>` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<Box<u8>>(), + "attempted to zero-initialize type `alloc::boxed::Box<u8>`, which is invalid" ); test_panic_msg( + || mem::uninitialized::<Box<u8>>(), + "attempted to leave type `alloc::boxed::Box<u8>` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&[i32]>(), + "attempted to zero-initialize type `&[i32]`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&[i32]>(), + "attempted to leave type `&[i32]` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&(u8, [u8])>(), + "attempted to zero-initialize type `&(u8, [u8])`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&(u8, [u8])>(), + "attempted to leave type `&(u8, [u8])` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&dyn Send>(), + "attempted to zero-initialize type `&dyn core::marker::Send`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&dyn Send>(), + "attempted to leave type `&dyn core::marker::Send` uninitialized, which is invalid" + ); + + test_panic_msg( || mem::zeroed::<*const dyn Send>(), "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid" ); + test_panic_msg( + || mem::uninitialized::<*const dyn Send>(), + "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid" + ); test_panic_msg( - || mem::uninitialized::<(NonNull<u32>, u32, u32)>(), - "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, \ + || mem::uninitialized::<NoNullVariant>(), + "attempted to leave type `NoNullVariant` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<NoNullVariant>(), + "attempted to zero-initialize type `NoNullVariant`, \ which is invalid" ); test_panic_msg( - || mem::zeroed::<(NonNull<u32>, u32, u32)>(), - "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \ + || mem::zeroed::<OneVariant_Ref>(), + "attempted to zero-initialize type `OneVariant_Ref`, \ which is invalid" ); + test_panic_msg( + || mem::uninitialized::<OneVariant_Ref>(), + "attempted to leave type `OneVariant_Ref` uninitialized, which is invalid" + ); + // Types where both are invalid, but we allow uninit since the 0x01-filling is not LLVM UB. test_panic_msg( - || mem::uninitialized::<OneVariant_NonZero>(), - "attempted to leave type `OneVariant_NonZero` uninitialized, \ + || mem::zeroed::<fn()>(), + "attempted to zero-initialize type `fn()`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<fn()>(), + "attempted to leave type `fn()` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&()>(), + "attempted to zero-initialize type `&()`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&()>(), + "attempted to leave type `&()` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&[u8]>(), + "attempted to zero-initialize type `&[u8]`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&[u8]>(), + "attempted to leave type `&[u8]` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&str>(), + "attempted to zero-initialize type `&str`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&str>(), + "attempted to leave type `&str` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<(NonNull<u32>, u32, u32)>(), + "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \ which is invalid" ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<(NonNull<u32>, u32, u32)>(), + "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, which is invalid" + ); + test_panic_msg( || mem::zeroed::<OneVariant_NonZero>(), "attempted to zero-initialize type `OneVariant_NonZero`, \ which is invalid" ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<OneVariant_NonZero>(), + "attempted to leave type `OneVariant_NonZero` uninitialized, which is invalid" + ); + // Types where both are invalid but we allow the zeroed form since it is not LLVM UB. + test_panic_msg_only_if_strict( + || mem::zeroed::<LR_NonZero>(), + "attempted to zero-initialize type `LR_NonZero`, which is invalid" + ); test_panic_msg( || mem::uninitialized::<LR_NonZero>(), "attempted to leave type `LR_NonZero` uninitialized, which is invalid" ); + test_panic_msg_only_if_strict( + || mem::zeroed::<ManuallyDrop<LR_NonZero>>(), + "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \ + which is invalid" + ); test_panic_msg( || mem::uninitialized::<ManuallyDrop<LR_NonZero>>(), "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>` uninitialized, \ which is invalid" ); - test_panic_msg( - || mem::uninitialized::<NoNullVariant>(), - "attempted to leave type `NoNullVariant` uninitialized, \ - which is invalid" + // Some strict-only things + test_panic_msg_only_if_strict( + || mem::uninitialized::<i32>(), + "attempted to leave type `i32` uninitialized, which is invalid" ); - test_panic_msg( - || mem::zeroed::<NoNullVariant>(), - "attempted to zero-initialize type `NoNullVariant`, \ - which is invalid" + test_panic_msg_only_if_strict( + || mem::uninitialized::<*const ()>(), + "attempted to leave type `*const ()` uninitialized, which is invalid" ); - // Types that can be zero, but not uninit. - test_panic_msg( - || mem::uninitialized::<bool>(), - "attempted to leave type `bool` uninitialized, which is invalid" + test_panic_msg_only_if_strict( + || mem::uninitialized::<[i32; 1]>(), + "attempted to leave type `[i32; 1]` uninitialized, which is invalid" ); + test_panic_msg_only_if_strict( + || mem::zeroed::<[NonNull<()>; 1]>(), + "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid" + ); + + // Types that can be zero, but not uninit (though some are mitigated). + let _val = mem::zeroed::<LR>(); test_panic_msg( || mem::uninitialized::<LR>(), "attempted to leave type `LR` uninitialized, which is invalid" ); + let _val = mem::zeroed::<ManuallyDrop<LR>>(); test_panic_msg( || mem::uninitialized::<ManuallyDrop<LR>>(), "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid" ); - // Some things that should work. let _val = mem::zeroed::<bool>(); - let _val = mem::zeroed::<LR>(); - let _val = mem::zeroed::<ManuallyDrop<LR>>(); + test_panic_msg_only_if_strict( + || mem::uninitialized::<bool>(), + "attempted to leave type `bool` uninitialized, which is invalid" + ); + let _val = mem::zeroed::<OneVariant>(); + test_panic_msg_only_if_strict( + || mem::uninitialized::<OneVariant>(), + "attempted to leave type `OneVariant` uninitialized, which is invalid" + ); + + // Some things that are actually allowed. let _val = mem::zeroed::<Option<&'static i32>>(); let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>(); let _val = mem::zeroed::<[!; 0]>(); @@ -234,59 +373,5 @@ fn main() { let _val = mem::uninitialized::<[!; 0]>(); let _val = mem::uninitialized::<()>(); let _val = mem::uninitialized::<ZeroSized>(); - - if cfg!(strict) { - test_panic_msg( - || mem::uninitialized::<i32>(), - "attempted to leave type `i32` uninitialized, which is invalid" - ); - - test_panic_msg( - || mem::uninitialized::<*const ()>(), - "attempted to leave type `*const ()` uninitialized, which is invalid" - ); - - test_panic_msg( - || mem::uninitialized::<[i32; 1]>(), - "attempted to leave type `[i32; 1]` uninitialized, which is invalid" - ); - - test_panic_msg( - || mem::zeroed::<NonNull<()>>(), - "attempted to zero-initialize type `core::ptr::non_null::NonNull<()>`, which is invalid" - ); - - test_panic_msg( - || mem::zeroed::<[NonNull<()>; 1]>(), - "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid" - ); - - // FIXME(#66151) we conservatively do not error here yet (by default). - test_panic_msg( - || mem::zeroed::<LR_NonZero>(), - "attempted to zero-initialize type `LR_NonZero`, which is invalid" - ); - - test_panic_msg( - || mem::zeroed::<ManuallyDrop<LR_NonZero>>(), - "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \ - which is invalid" - ); - } else { - // These are UB because they have not been officially blessed, but we await the resolution - // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing - // anything about that. - let _val = mem::uninitialized::<i32>(); - let _val = mem::uninitialized::<*const ()>(); - - // These are UB, but best to test them to ensure we don't become unintentionally - // stricter. - - // It's currently unchecked to create invalid enums and values inside arrays. - let _val = mem::zeroed::<LR_NonZero>(); - let _val = mem::zeroed::<[LR_NonZero; 1]>(); - let _val = mem::zeroed::<[NonNull<()>; 1]>(); - let _val = mem::uninitialized::<[NonNull<()>; 1]>(); - } } } |