Skip to content

Commit 09d9c09

Browse files
authored
Rollup merge of #89741 - sdroege:arc-rc-from-inner-unsafe, r=Mark-Simulacrum
Mark `Arc::from_inner` / `Rc::from_inner` as unsafe While it's an internal function, it is easy to create invalid Arc/Rcs to a dangling pointer with it. Fixes #89740
2 parents 93542a8 + 2e2c38e commit 09d9c09

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

library/alloc/src/rc.rs

+31-20
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,12 @@ impl<T: ?Sized> Rc<T> {
341341
unsafe { self.ptr.as_ref() }
342342
}
343343

344-
fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
344+
unsafe fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
345345
Self { ptr, phantom: PhantomData }
346346
}
347347

348348
unsafe fn from_ptr(ptr: *mut RcBox<T>) -> Self {
349-
Self::from_inner(unsafe { NonNull::new_unchecked(ptr) })
349+
unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) }
350350
}
351351
}
352352

@@ -367,9 +367,11 @@ impl<T> Rc<T> {
367367
// pointers, which ensures that the weak destructor never frees
368368
// the allocation while the strong destructor is running, even
369369
// if the weak pointer is stored inside the strong one.
370-
Self::from_inner(
371-
Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(),
372-
)
370+
unsafe {
371+
Self::from_inner(
372+
Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(),
373+
)
374+
}
373375
}
374376

375377
/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
@@ -420,16 +422,16 @@ impl<T> Rc<T> {
420422
// otherwise.
421423
let data = data_fn(&weak);
422424

423-
unsafe {
425+
let strong = unsafe {
424426
let inner = init_ptr.as_ptr();
425427
ptr::write(ptr::addr_of_mut!((*inner).value), data);
426428

427429
let prev_value = (*inner).strong.get();
428430
debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
429431
(*inner).strong.set(1);
430-
}
431432

432-
let strong = Rc::from_inner(init_ptr);
433+
Rc::from_inner(init_ptr)
434+
};
433435

434436
// Strong references should collectively own a shared weak reference,
435437
// so don't run the destructor for our old weak reference.
@@ -521,10 +523,12 @@ impl<T> Rc<T> {
521523
// pointers, which ensures that the weak destructor never frees
522524
// the allocation while the strong destructor is running, even
523525
// if the weak pointer is stored inside the strong one.
524-
Ok(Self::from_inner(
525-
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
526-
.into(),
527-
))
526+
unsafe {
527+
Ok(Self::from_inner(
528+
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
529+
.into(),
530+
))
531+
}
528532
}
529533

530534
/// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails
@@ -746,7 +750,7 @@ impl<T> Rc<mem::MaybeUninit<T>> {
746750
#[unstable(feature = "new_uninit", issue = "63291")]
747751
#[inline]
748752
pub unsafe fn assume_init(self) -> Rc<T> {
749-
Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast())
753+
unsafe { Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) }
750754
}
751755
}
752756

@@ -1214,9 +1218,11 @@ impl Rc<dyn Any> {
12141218
/// ```
12151219
pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
12161220
if (*self).is::<T>() {
1217-
let ptr = self.ptr.cast::<RcBox<T>>();
1218-
forget(self);
1219-
Ok(Rc::from_inner(ptr))
1221+
unsafe {
1222+
let ptr = self.ptr.cast::<RcBox<T>>();
1223+
forget(self);
1224+
Ok(Rc::from_inner(ptr))
1225+
}
12201226
} else {
12211227
Err(self)
12221228
}
@@ -1489,8 +1495,10 @@ impl<T: ?Sized> Clone for Rc<T> {
14891495
/// ```
14901496
#[inline]
14911497
fn clone(&self) -> Rc<T> {
1492-
self.inner().inc_strong();
1493-
Self::from_inner(self.ptr)
1498+
unsafe {
1499+
self.inner().inc_strong();
1500+
Self::from_inner(self.ptr)
1501+
}
14941502
}
14951503
}
14961504

@@ -2245,11 +2253,14 @@ impl<T: ?Sized> Weak<T> {
22452253
#[stable(feature = "rc_weak", since = "1.4.0")]
22462254
pub fn upgrade(&self) -> Option<Rc<T>> {
22472255
let inner = self.inner()?;
2256+
22482257
if inner.strong() == 0 {
22492258
None
22502259
} else {
2251-
inner.inc_strong();
2252-
Some(Rc::from_inner(self.ptr))
2260+
unsafe {
2261+
inner.inc_strong();
2262+
Some(Rc::from_inner(self.ptr))
2263+
}
22532264
}
22542265
}
22552266

library/alloc/src/sync.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
252252
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
253253

254254
impl<T: ?Sized> Arc<T> {
255-
fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
255+
unsafe fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
256256
Self { ptr, phantom: PhantomData }
257257
}
258258

@@ -348,7 +348,7 @@ impl<T> Arc<T> {
348348
weak: atomic::AtomicUsize::new(1),
349349
data,
350350
};
351-
Self::from_inner(Box::leak(x).into())
351+
unsafe { Self::from_inner(Box::leak(x).into()) }
352352
}
353353

354354
/// Constructs a new `Arc<T>` using a weak reference to itself. Attempting
@@ -397,7 +397,7 @@ impl<T> Arc<T> {
397397

398398
// Now we can properly initialize the inner value and turn our weak
399399
// reference into a strong reference.
400-
unsafe {
400+
let strong = unsafe {
401401
let inner = init_ptr.as_ptr();
402402
ptr::write(ptr::addr_of_mut!((*inner).data), data);
403403

@@ -415,9 +415,9 @@ impl<T> Arc<T> {
415415
// possible with safe code alone.
416416
let prev_value = (*inner).strong.fetch_add(1, Release);
417417
debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
418-
}
419418

420-
let strong = Arc::from_inner(init_ptr);
419+
Arc::from_inner(init_ptr)
420+
};
421421

422422
// Strong references should collectively own a shared weak reference,
423423
// so don't run the destructor for our old weak reference.
@@ -529,7 +529,7 @@ impl<T> Arc<T> {
529529
weak: atomic::AtomicUsize::new(1),
530530
data,
531531
})?;
532-
Ok(Self::from_inner(Box::leak(x).into()))
532+
unsafe { Ok(Self::from_inner(Box::leak(x).into())) }
533533
}
534534

535535
/// Constructs a new `Arc` with uninitialized contents, returning an error
@@ -743,7 +743,7 @@ impl<T> Arc<mem::MaybeUninit<T>> {
743743
#[must_use = "`self` will be dropped if the result is not used"]
744744
#[inline]
745745
pub unsafe fn assume_init(self) -> Arc<T> {
746-
Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast())
746+
unsafe { Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) }
747747
}
748748
}
749749

@@ -1341,7 +1341,7 @@ impl<T: ?Sized> Clone for Arc<T> {
13411341
abort();
13421342
}
13431343

1344-
Self::from_inner(self.ptr)
1344+
unsafe { Self::from_inner(self.ptr) }
13451345
}
13461346
}
13471347

@@ -1668,9 +1668,11 @@ impl Arc<dyn Any + Send + Sync> {
16681668
T: Any + Send + Sync + 'static,
16691669
{
16701670
if (*self).is::<T>() {
1671-
let ptr = self.ptr.cast::<ArcInner<T>>();
1672-
mem::forget(self);
1673-
Ok(Arc::from_inner(ptr))
1671+
unsafe {
1672+
let ptr = self.ptr.cast::<ArcInner<T>>();
1673+
mem::forget(self);
1674+
Ok(Arc::from_inner(ptr))
1675+
}
16741676
} else {
16751677
Err(self)
16761678
}
@@ -1899,7 +1901,7 @@ impl<T: ?Sized> Weak<T> {
18991901
// value can be initialized after `Weak` references have already been created. In that case, we
19001902
// expect to observe the fully initialized value.
19011903
match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
1902-
Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above
1904+
Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above
19031905
Err(old) => n = old,
19041906
}
19051907
}

0 commit comments

Comments
 (0)