From: Ralf Jung Date: Wed, 14 Sep 2022 07:39:38 +0000 (+0200) Subject: add update on the current state on ptr2int transmutation X-Git-Url: https://git.ralfj.de/web.git/commitdiff_plain/45f7eb108dbf4258d7bd962fe15b64773fa633ae add update on the current state on ptr2int transmutation --- diff --git a/ralf/_posts/2022-04-11-provenance-exposed.md b/ralf/_posts/2022-04-11-provenance-exposed.md index 53d0b84..39237ae 100644 --- a/ralf/_posts/2022-04-11-provenance-exposed.md +++ b/ralf/_posts/2022-04-11-provenance-exposed.md @@ -277,13 +277,19 @@ Because of that, I think we should move towards discouraging, deprecating, or ev That means a cast is the only legal way to turn a pointer into an integer, and after the discussion above we got our casts covered. A [first careful step](https://github.com/rust-lang/rust/pull/95547) has recently been taken on this journey; the `mem::transmute` documentation now cautions against using this function to turn pointers into integers. +**Update (2022-09-14):** After a lot more discussion, the current model pursued by the Unsafe Code Guidelines WG is to say that pointer-to-integer transmutation is permitted, but just strips provenance without exposing it. +That means the program with the casts replaced by transmutation is UB, because the `ptr` it ends up dereferencing has invalid provenance. +However, the transmutation itself is not UB. +Basically, pointer-to-integer transmutation is equivalent to [the `addr` method](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.addr), with all its caveats -- in particular, transmuting a pointer to an integer and back is like calling `addr` and then calling [`ptr::invalid`](https://doc.rust-lang.org/nightly/std/ptr/fn.invalid.html); that is not a lossless round-trip. +This model has some nice properties that help compiler optimizations (such as removing unnecessary store-load round-trips). **/Update** + ## A new hope for Rust All in all, while the situation may be very complicated, I am actually more hopeful than ever that we can have both -- a precise memory model for Rust *and* all the optimizations we can hope for! The three core pillars of this approach are: - making pointer-integer casts "expose" the pointer's provenance, - offering `ptr.addr()` to learn a pointer's address *without* exposing its provenance, -- and disallowing pointer-integer transmutation. +- and disallowing pointer-integer transmutation round-trips. Together, they imply that we can optimize "nice" code (that follows Strict Provenance, and does not "expose" or use integer-pointer casts) perfectly, without any risk of breaking code that does use pointer-integer round-trips. In the easiest possible approach, the compiler can simply treat pointer-integer and integer-pointer casts as calls to some opaque external function. @@ -367,8 +373,8 @@ Because of all that, I think it is reasonable for Rust to make a different choic This was a long post, but I hope you found it worth reading. :) To summarize, my concrete calls for action in Rust are: -- Code that uses pointer-integer transmutation should migrate to regular casts or `MaybeUninit` transmutation ASAP. - I think we should declare pointer-integer transmutation Undefined Behavior and not accept such code as well-defined. +- Code that uses pointer-integer transmutation round-trips should migrate to regular casts or `MaybeUninit` transmutation ASAP. + I think we should declare pointer-integer transmutation as "losing" provenance, so code that assumes a lossless transmutation round-trip has Undefined Behavior. - Code that uses pointer-integer or integer-pointer *casts* might consider migrating to the Strict Provenance APIs. You can do this even on stable with [this polyfill crate](https://crates.io/crates/sptr). However, such code *is and remains* well-defined. It just might not be optimized as well as one could hope, it might not compile on CHERI, and Miri will probably miss some bugs.