-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Make uninit checks stricter but avoid issues for old hyper #99389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
85545dd
c84936e
6770c21
a2f44ac
a007e7b
5ee555c
eb1b384
a6ab54b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,31 @@ enum ZeroIsValid { | |
One(NonNull<()>) = 1, | ||
} | ||
|
||
#[rustfmt::skip] | ||
#[allow(dead_code)] | ||
enum SoManyVariants { | ||
A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, | ||
A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, | ||
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, | ||
A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, | ||
A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, | ||
A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, A90, A91, A92, | ||
A93, A94, A95, A96, A97, A98, A99, A100, A101, A102, A103, A104, A105, A106, | ||
A107, A108, A109, A110, A111, A112, A113, A114, A115, A116, A117, A118, A119, | ||
A120, A121, A122, A123, A124, A125, A126, A127, A128, A129, A130, A131, A132, | ||
A133, A134, A135, A136, A137, A138, A139, A140, A141, A142, A143, A144, A145, | ||
A146, A147, A148, A149, A150, A151, A152, A153, A154, A155, A156, A157, A158, | ||
A159, A160, A161, A162, A163, A164, A165, A166, A167, A168, A169, A170, A171, | ||
A172, A173, A174, A175, A176, A177, A178, A179, A180, A181, A182, A183, A184, | ||
A185, A186, A187, A188, A189, A190, A191, A192, A193, A194, A195, A196, A197, | ||
A198, A199, A200, A201, A202, A203, A204, A205, A206, A207, A208, A209, A210, | ||
A211, A212, A213, A214, A215, A216, A217, A218, A219, A220, A221, A222, A223, | ||
A224, A225, A226, A227, A228, A229, A230, A231, A232, A233, A234, A235, A236, | ||
A237, A238, A239, A240, A241, A242, A243, A244, A245, A246, A247, A248, A249, | ||
A250, A251, A252, A253, A254, A255, A256, | ||
} | ||
|
||
#[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 +97,19 @@ fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { | |
); | ||
} | ||
|
||
#[track_caller] | ||
// If strict mode is enabled, expect the msg. Otherwise, expect there to be no error. | ||
fn test_strict_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { | ||
let err = panic::catch_unwind(op).err(); | ||
|
||
let expectation = if cfg!(strict) { Some(&msg) } else { None }; | ||
|
||
assert_eq!( | ||
err.as_ref().and_then(|a| a.downcast_ref::<&str>()), | ||
expectation | ||
); | ||
} | ||
|
||
fn main() { | ||
unsafe { | ||
// Uninhabited types | ||
|
@@ -221,6 +259,50 @@ fn main() { | |
"attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<&'static [u8]>(), | ||
"attempted to leave type `&[u8]` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<&'static [u16]>(), | ||
"attempted to leave type `&[u16]` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<SoManyVariants>(), | ||
"attempted to leave type `SoManyVariants` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<[&'static [u16]; 1]>(), | ||
"attempted to leave type `[&[u16]; 1]` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<[NonNull<()>; 1]>(), | ||
"attempted to leave type `[core::ptr::non_null::NonNull<()>; 1]` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<(&[u8], &str, &())>(), | ||
"attempted to leave type `(&[u8], &str, &())` uninitialized, which is invalid" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one we could accept, if we wanted, by accepting all references to sized align-1-ZST... doesn't seem very important though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though allowing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could do, but I figure since not many people are actually making a reference to a ZST, no harm in forbidding it now. The changes here are rather arbitrary in their nature, we're only not panicking on the bits that we can't panic on just yet, while making the checks stricter where we can. Making an uninit Hyper doesn't make uninit refs to sized ZSTs, so I don't think we need to allow them here, even if it is somewhat inconsistent to forbid them. I'm fine with ignoring &() as well, I just don't feel it's needed. |
||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<[&(); 1]>(), | ||
"attempted to leave type `[&(); 1]` uninitialized, which is invalid" | ||
); | ||
|
||
test_panic_msg( | ||
|| mem::uninitialized::<[&dyn Send; 1]>(), | ||
"attempted to leave type `[&dyn core::marker::Send; 1]` uninitialized, which is invalid" | ||
); | ||
test_panic_msg( | ||
|| mem::uninitialized::<[*const dyn Send; 1]>(), | ||
"attempted to leave type `[*const dyn core::marker::Send; 1]` uninitialized, which is invalid" | ||
); | ||
|
||
// Some things that should work. | ||
let _val = mem::zeroed::<bool>(); | ||
let _val = mem::zeroed::<LR>(); | ||
|
@@ -230,63 +312,61 @@ fn main() { | |
let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>(); | ||
let _val = mem::zeroed::<[!; 0]>(); | ||
let _val = mem::zeroed::<ZeroIsValid>(); | ||
let _val = mem::zeroed::<SoManyVariants>(); | ||
let _val = mem::uninitialized::<[SoManyVariants; 0]>(); | ||
let _val = mem::uninitialized::<MaybeUninit<bool>>(); | ||
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]>(); | ||
} | ||
// 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. | ||
test_strict_panic_msg( | ||
|| mem::uninitialized::<i32>(), | ||
"attempted to leave type `i32` uninitialized, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::uninitialized::<*const ()>(), | ||
"attempted to leave type `*const ()` uninitialized, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::uninitialized::<[i32; 1]>(), | ||
"attempted to leave type `[i32; 1]` uninitialized, which is invalid" | ||
); | ||
|
||
// These are UB, but making them panic breaks too many crates at the moment. | ||
test_strict_panic_msg( | ||
|| mem::zeroed::<[(&[u8], &str); 1]>(), | ||
"attempted to zero-initialize type `[(&[u8], &str); 1]`, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::uninitialized::<[(&[u8], &str); 1]>(), | ||
"attempted to leave type `[(&[u8], &str); 1]` uninitialized, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::zeroed::<[NonNull<()>; 1]>(), | ||
"attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::zeroed::<LR_NonZero>(), | ||
"attempted to zero-initialize type `LR_NonZero`, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::zeroed::<[LR_NonZero; 1]>(), | ||
"attempted to zero-initialize type `[LR_NonZero; 1]`, which is invalid" | ||
); | ||
|
||
test_strict_panic_msg( | ||
|| mem::zeroed::<ManuallyDrop<LR_NonZero>>(), | ||
"attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \ | ||
which is invalid" | ||
); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.