diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1ff1c3c834f4e..8c70b0a913a98 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -571,9 +571,19 @@ impl Rc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { - let ptr: *const T = &*this; + let ptr: *mut RcBox = NonNull::as_ptr(this.ptr); + let fake_ptr = ptr as *mut T; mem::forget(this); - ptr + + // SAFETY: This cannot go through Deref::deref. + // Instead, we manually offset the pointer rather than manifesting a reference. + // This is so that the returned pointer retains the same provenance as our pointer. + // This is required so that e.g. `get_mut` can write through the pointer + // after the Rc is recovered through `from_raw`. + unsafe { + let offset = data_offset(&(*ptr).value); + set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset)) + } } /// Constructs an `Rc` from a raw pointer. diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 19b0086fa333c..5c1fa17a626d1 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -551,9 +551,19 @@ impl Arc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { - let ptr: *const T = &*this; + let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); + let fake_ptr = ptr as *mut T; mem::forget(this); - ptr + + // SAFETY: This cannot go through Deref::deref. + // Instead, we manually offset the pointer rather than manifesting a reference. + // This is so that the returned pointer retains the same provenance as our pointer. + // This is required so that e.g. `get_mut` can write through the pointer + // after the Arc is recovered through `from_raw`. + unsafe { + let offset = data_offset(&(*ptr).data); + set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset)) + } } /// Constructs an `Arc` from a raw pointer.