Skip to content

Work around bad ptr::with_addr codegen in core::ptr #96538

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,25 @@ impl<T: ?Sized> *const T {
// In the mean-time, this operation is defined to be "as if" it was
// a wrapping_offset, so we can emulate it as such. This should properly
// restore pointer provenance even under today's compiler.
let self_addr = self.addr() as isize;
let dest_addr = addr as isize;
let offset = dest_addr.wrapping_sub(self_addr);

// This is the canonical desugarring of this operation
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
let self_addr = self.addr();
// In an ideal world (err, an ideal world we'd have an intrinsic, but
// short of that), we'd implement this as follows:
// ```
// let offset = (addr as isize).wrapping_sub(self_addr as isize);
// self.cast::<u8>().wrapping_offset(offset).cast::<T>()
// ```
// This is the canonical desugaring of this operation, and is compatible
// with targets which don't allow large wrapping add/sub/offset
// operations, including CHERI.
//
// Unfortunately, this causes worse codegen than the following
// implementation, which should be correct on all targets we currently
// support (at the moment AFAICT, we don't yet support CHERI, or we'd
// special-case it to use the desugaring listed above).
//
// As a result, we use the following implementation, which would be
// wrong on CHERI, but right everywhere else.
self.cast::<u8>().wrapping_add(addr).wrapping_sub(self_addr).cast::<T>()
}

/// Creates a new pointer by mapping `self`'s address to a new one.
Expand Down
25 changes: 19 additions & 6 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,25 @@ impl<T: ?Sized> *mut T {
// In the mean-time, this operation is defined to be "as if" it was
// a wrapping_offset, so we can emulate it as such. This should properly
// restore pointer provenance even under today's compiler.
let self_addr = self.addr() as isize;
let dest_addr = addr as isize;
let offset = dest_addr.wrapping_sub(self_addr);

// This is the canonical desugarring of this operation
self.cast::<u8>().wrapping_offset(offset).cast::<T>()
let self_addr = self.addr();
// In an ideal world (err, an ideal world we'd have an intrinsic, but
// short of that), we'd implement this as follows:
// ```
// let offset = (addr as isize).wrapping_sub(self_addr as isize);
// self.cast::<u8>().wrapping_offset(offset).cast::<T>()
// ```
// This is the canonical desugaring of this operation, and is compatible
// with targets which don't allow large wrapping add/sub/offset
// operations, including CHERI.
//
// Unfortunately, this causes worse codegen than the following
// implementation, which should be correct on all targets we currently
// support (at the moment AFAICT, we don't yet support CHERI, or we'd
// special-case it to use the desugaring listed above).
//
// As a result, we use the following implementation, which would be
// wrong on CHERI, but right everywhere else.
self.cast::<u8>().wrapping_add(addr).wrapping_sub(self_addr).cast::<T>()
}

/// Creates a new pointer by mapping `self`'s address to a new one.
Expand Down