From be28971594764ed20a9a42211d1b27ee76922ec9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Mar 2024 13:29:15 +0100 Subject: [PATCH] transmute: caution against int2ptr transmutation --- library/core/src/intrinsics.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 86b9a39d68a67..4c4dbef0352f4 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1169,14 +1169,6 @@ extern "rust-intrinsic" { /// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly /// unsafe**. `transmute` should be the absolute last resort. /// - /// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub], - /// unless the pointer was originally created *from* an integer. - /// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling], - /// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.) - /// Any attempt to use the resulting value for integer operations will abort const-evaluation. - /// (And even outside `const`, such transmutation is touching on many unspecified aspects of the - /// Rust memory model and should be avoided. See below for alternatives.) - /// /// Because `transmute` is a by-value operation, alignment of the *transmuted values /// themselves* is not a concern. As with any other function, the compiler already ensures /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point @@ -1187,6 +1179,29 @@ extern "rust-intrinsic" { /// /// [ub]: ../../reference/behavior-considered-undefined.html /// + /// # Transmutation between pointers and integers + /// + /// Special care has to be taken when transmuting between pointers and integers, + /// e.g. transmuting between `*const ()` and `usize`. + /// + /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], + /// unless the pointer was originally created *from* an integer. + /// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::dangling], + /// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.) + /// Any attempt to use the resulting value for integer operations will abort const-evaluation. + /// (And even outside `const`, such transmutation is touching on many unspecified aspects of the + /// Rust memory model and should be avoided. See below for alternatives.) + /// + /// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not* + /// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed + /// this way is currently considered Undefined Behavior. + /// + /// All this also applies when the integer is nested inside an array, tuple, struct, or enum. + /// However, `MaybeUninit` is not considered an integer type for the purpose of this + /// section. Transmuting `*const ()` to `MaybeUninit` is fine---but then calling + /// `assume_init()` on that result is considered as completing the pointer-to-integer transmute + /// and thus runs into the issues discussed above. + /// /// # Examples /// /// There are a few things that `transmute` is really useful for.