From b6d7805a0b97bfbb05460493336a77bc72dc5405 Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 17 Feb 2024 21:27:11 +0100 Subject: [PATCH] generate `getelementptr` instead of `inttoptr` for `ptr::invalid` --- library/core/src/ptr/mod.rs | 26 ++++++++++++++++---------- tests/codegen/strict-provenance.rs | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 tests/codegen/strict-provenance.rs diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index fc5b08c9801a8..41f2e37676807 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -590,11 +590,14 @@ pub const fn null_mut() -> *mut T { #[unstable(feature = "strict_provenance", issue = "95228")] pub const fn without_provenance(addr: usize) -> *const T { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // 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) } + // FIXME(maybe): simply transmute the address once codegen lowers that correctly. + // We offset the null pointer instead of using a cast so that this lowers to + // getelementptr instead of inttoptr. + // We use transmute instead of casting so that in miri the pointer truly + // has no provenance. + // SAFETY: on all current platforms, usize and pointers have the same layout, + // and the validity invariant of pointers is the same as that of integers + unsafe { mem::transmute::<_, *const T>(0usize).wrapping_byte_add(addr) } } /// Creates a new pointer that is dangling, but well-aligned. @@ -632,11 +635,14 @@ pub const fn dangling() -> *const T { #[unstable(feature = "strict_provenance", issue = "95228")] pub const fn without_provenance_mut(addr: usize) -> *mut T { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. - // 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) } + // FIXME(maybe): simply transmute the address once codegen lowers that correctly. + // We offset the null pointer instead of using a cast so that this lowers to + // getelementptr instead of inttoptr. + // We use transmute instead of casting so that in miri the pointer truly + // has no provenance. + // SAFETY: on all current platforms, usize and pointers have the same layout, + // and the validity invariant of pointers is the same as that of integers + unsafe { mem::transmute::<_, *mut T>(0usize).wrapping_byte_add(addr) } } /// Creates a new pointer that is dangling, but well-aligned. diff --git a/tests/codegen/strict-provenance.rs b/tests/codegen/strict-provenance.rs new file mode 100644 index 0000000000000..2bbdc3fc9a756 --- /dev/null +++ b/tests/codegen/strict-provenance.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] +#![feature(strict_provenance)] + +use std::ptr; + +// CHECK-LABEL: ptr @without_provenance( +// CHECK-SAME: [[USIZE:i[0-9]+]] noundef %addr) +#[no_mangle] +fn without_provenance(addr: usize) -> *const () { + // CHECK: start + // CHECK-NEXT: %0 = getelementptr i8, ptr null, [[USIZE]] %addr + // CHECK-NEXT: ret ptr %0 + ptr::without_provenance(addr) +}