about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2022-05-21 11:39:50 +0200
committerGitHub <noreply@github.com>2022-05-21 11:39:50 +0200
commit6fef5f1e243c30deec7728616cdcf21c4547ab9e (patch)
treed4240968f37b082ffb5261b45d0cdce26181e239
parente5c7b21f395d57e870eb90292726d0824a34cd10 (diff)
parent31c3c0449807d22a0f10e7a290a8e4ed114b98d4 (diff)
downloadrust-6fef5f1e243c30deec7728616cdcf21c4547ab9e.tar.gz
rust-6fef5f1e243c30deec7728616cdcf21c4547ab9e.zip
Rollup merge of #97219 - RalfJung:ptr-invalid, r=thomcc
make ptr::invalid not the same as a regular int2ptr cast

In Miri, we would like to distinguish `ptr::invalid` from `ptr::from_exposed_provenance`, so that we can provide better diagnostics issues like https://github.com/rust-lang/miri/issues/2134, and so that we can detect the UB in programs like
```rust
fn main() {
    let x = 0u8;
    let original_ptr = &x as *const u8;
    let addr = original_ptr.expose_addr();
    let new_ptr: *const u8 = core::ptr::invalid(addr);
    unsafe {
        dbg!(*new_ptr);
    }
}
```

To achieve that, the two functions need to have different implementations. Currently, both are just `as` casts. We *could* add an intrinsic for this, but it turns out `transmute` already has the right behavior, at least as far as Miri is concerned. So I propose we just use that.

Cc `@Gankra`
-rw-r--r--library/core/src/ptr/mod.rs12
1 files changed, 10 insertions, 2 deletions
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index ba8b0670147..dc229c9ff9b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -555,7 +555,11 @@ pub const fn null_mut<T>() -> *mut T {
 #[unstable(feature = "strict_provenance", issue = "95228")]
 pub const fn invalid<T>(addr: usize) -> *const T {
     // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
-    addr as *const T
+    // We use transmute rather than a cast so tools like Miri can tell that this
+    // is *not* the same as from_exposed_addr.
+    // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
+    // pointer).
+    unsafe { mem::transmute(addr) }
 }
 
 /// Creates an invalid mutable pointer with the given address.
@@ -582,7 +586,11 @@ pub const fn invalid<T>(addr: usize) -> *const T {
 #[unstable(feature = "strict_provenance", issue = "95228")]
 pub const fn invalid_mut<T>(addr: usize) -> *mut T {
     // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
-    addr as *mut T
+    // We use transmute rather than a cast so tools like Miri can tell that this
+    // is *not* the same as from_exposed_addr.
+    // SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
+    // pointer).
+    unsafe { mem::transmute(addr) }
 }
 
 /// Convert an address back to a pointer, picking up a previously 'exposed' provenance.