Skip to content

Commit b5b6760

Browse files
committed
Weak::into_raw shouldn't translate sentinel value
1 parent 747dbcb commit b5b6760

File tree

2 files changed

+21
-27
lines changed

2 files changed

+21
-27
lines changed

library/alloc/src/rc.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ impl<T: ?Sized> Rc<T> {
848848
pub fn downgrade(this: &Self) -> Weak<T> {
849849
this.inner().inc_weak();
850850
// Make sure we do not create a dangling Weak
851-
debug_assert!(!is_dangling(this.ptr));
851+
debug_assert!(!is_dangling(this.ptr.as_ptr()));
852852
Weak { ptr: this.ptr }
853853
}
854854

@@ -1837,8 +1837,8 @@ impl<T> Weak<T> {
18371837
}
18381838
}
18391839

1840-
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
1841-
let address = ptr.as_ptr() as *mut () as usize;
1840+
pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
1841+
let address = ptr as *mut () as usize;
18421842
address == usize::MAX
18431843
}
18441844

@@ -1879,17 +1879,15 @@ impl<T: ?Sized> Weak<T> {
18791879
pub fn as_ptr(&self) -> *const T {
18801880
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
18811881

1882-
if is_dangling(self.ptr) {
1883-
// If the pointer is dangling, we return a null pointer as the dangling sentinel.
1884-
// We can't return the usize::MAX sentinel, as that could valid if T is ZST.
1885-
// SAFETY: we have to return a known sentinel here that cannot be produced for
1886-
// a valid pointer, so that `from_raw` can reverse this transformation.
1887-
(ptr as *mut T).set_ptr_value(ptr::null_mut())
1882+
if is_dangling(ptr) {
1883+
// If the pointer is dangling, we return the sentinel directly. This cannot be
1884+
// a valid payload address, as it is at least as aligned as RcBox (usize).
1885+
ptr as *const T
18881886
} else {
18891887
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
18901888
// The payload may be dropped at this point, and we have to maintain provenance,
18911889
// so use raw pointer manipulation.
1892-
unsafe { &raw mut (*ptr).value }
1890+
unsafe { &raw const (*ptr).value }
18931891
}
18941892
}
18951893

@@ -1973,10 +1971,9 @@ impl<T: ?Sized> Weak<T> {
19731971
pub unsafe fn from_raw(ptr: *const T) -> Self {
19741972
// See Weak::as_ptr for context on how the input pointer is derived.
19751973

1976-
let ptr = if ptr.is_null() {
1977-
// If we get a null pointer, this is a dangling weak.
1978-
// SAFETY: this is the same sentinel as used in Weak::new and is_dangling
1979-
(ptr as *mut RcBox<T>).set_ptr_value(usize::MAX as *mut _)
1974+
let ptr = if is_dangling(ptr as *mut T) {
1975+
// This is a dangling Weak.
1976+
ptr as *mut RcBox<T>
19801977
} else {
19811978
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
19821979
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
@@ -2052,7 +2049,7 @@ impl<T: ?Sized> Weak<T> {
20522049
/// (i.e., when this `Weak` was created by `Weak::new`).
20532050
#[inline]
20542051
fn inner(&self) -> Option<WeakInner<'_>> {
2055-
if is_dangling(self.ptr) {
2052+
if is_dangling(self.ptr.as_ptr()) {
20562053
None
20572054
} else {
20582055
// We are careful to *not* create a reference covering the "data" field, as

library/alloc/src/sync.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ impl<T: ?Sized> Arc<T> {
885885
match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) {
886886
Ok(_) => {
887887
// Make sure we do not create a dangling Weak
888-
debug_assert!(!is_dangling(this.ptr));
888+
debug_assert!(!is_dangling(this.ptr.as_ptr()));
889889
return Weak { ptr: this.ptr };
890890
}
891891
Err(old) => cur = old,
@@ -1664,12 +1664,10 @@ impl<T: ?Sized> Weak<T> {
16641664
pub fn as_ptr(&self) -> *const T {
16651665
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
16661666

1667-
if is_dangling(self.ptr) {
1668-
// If the pointer is dangling, we return a null pointer as the dangling sentinel.
1669-
// We can't return the usize::MAX sentinel, as that could valid if T is ZST.
1670-
// SAFETY: we have to return a known sentinel here that cannot be produced for
1671-
// a valid pointer, so that `from_raw` can reverse this transformation.
1672-
(ptr as *mut T).set_ptr_value(ptr::null_mut())
1667+
if is_dangling(ptr) {
1668+
// If the pointer is dangling, we return the sentinel directly. This cannot be
1669+
// a valid payload address, as it is at least as aligned as ArcInner (usize).
1670+
ptr as *const T
16731671
} else {
16741672
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
16751673
// The payload may be dropped at this point, and we have to maintain provenance,
@@ -1758,10 +1756,9 @@ impl<T: ?Sized> Weak<T> {
17581756
pub unsafe fn from_raw(ptr: *const T) -> Self {
17591757
// See Weak::as_ptr for context on how the input pointer is derived.
17601758

1761-
let ptr = if ptr.is_null() {
1762-
// If we get a null pointer, this is a dangling weak.
1763-
// SAFETY: this is the same sentinel as used in Weak::new and is_dangling
1764-
(ptr as *mut ArcInner<T>).set_ptr_value(usize::MAX as *mut _)
1759+
let ptr = if is_dangling(ptr as *mut T) {
1760+
// This is a dangling Weak.
1761+
ptr as *mut ArcInner<T>
17651762
} else {
17661763
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
17671764
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
@@ -1877,7 +1874,7 @@ impl<T: ?Sized> Weak<T> {
18771874
/// (i.e., when this `Weak` was created by `Weak::new`).
18781875
#[inline]
18791876
fn inner(&self) -> Option<WeakInner<'_>> {
1880-
if is_dangling(self.ptr) {
1877+
if is_dangling(self.ptr.as_ptr()) {
18811878
None
18821879
} else {
18831880
// We are careful to *not* create a reference covering the "data" field, as

0 commit comments

Comments
 (0)