Skip to content

Commit 2e2c38e

Browse files
committed
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
1 parent 0c87288 commit 2e2c38e

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
@@ -333,12 +333,12 @@ impl<T: ?Sized> Rc<T> {
333333
unsafe { self.ptr.as_ref() }
334334
}
335335

336-
fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
336+
unsafe fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
337337
Self { ptr, phantom: PhantomData }
338338
}
339339

340340
unsafe fn from_ptr(ptr: *mut RcBox<T>) -> Self {
341-
Self::from_inner(unsafe { NonNull::new_unchecked(ptr) })
341+
unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) }
342342
}
343343
}
344344

@@ -359,9 +359,11 @@ impl<T> Rc<T> {
359359
// pointers, which ensures that the weak destructor never frees
360360
// the allocation while the strong destructor is running, even
361361
// if the weak pointer is stored inside the strong one.
362-
Self::from_inner(
363-
Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(),
364-
)
362+
unsafe {
363+
Self::from_inner(
364+
Box::leak(box RcBox { strong: Cell::new(1), weak: Cell::new(1), value }).into(),
365+
)
366+
}
365367
}
366368

367369
/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
@@ -412,16 +414,16 @@ impl<T> Rc<T> {
412414
// otherwise.
413415
let data = data_fn(&weak);
414416

415-
unsafe {
417+
let strong = unsafe {
416418
let inner = init_ptr.as_ptr();
417419
ptr::write(ptr::addr_of_mut!((*inner).value), data);
418420

419421
let prev_value = (*inner).strong.get();
420422
debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
421423
(*inner).strong.set(1);
422-
}
423424

424-
let strong = Rc::from_inner(init_ptr);
425+
Rc::from_inner(init_ptr)
426+
};
425427

426428
// Strong references should collectively own a shared weak reference,
427429
// so don't run the destructor for our old weak reference.
@@ -511,10 +513,12 @@ impl<T> Rc<T> {
511513
// pointers, which ensures that the weak destructor never frees
512514
// the allocation while the strong destructor is running, even
513515
// if the weak pointer is stored inside the strong one.
514-
Ok(Self::from_inner(
515-
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
516-
.into(),
517-
))
516+
unsafe {
517+
Ok(Self::from_inner(
518+
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
519+
.into(),
520+
))
521+
}
518522
}
519523

520524
/// Constructs a new `Rc` with uninitialized contents, returning an error if the allocation fails
@@ -733,7 +737,7 @@ impl<T> Rc<mem::MaybeUninit<T>> {
733737
#[unstable(feature = "new_uninit", issue = "63291")]
734738
#[inline]
735739
pub unsafe fn assume_init(self) -> Rc<T> {
736-
Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast())
740+
unsafe { Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) }
737741
}
738742
}
739743

@@ -1199,9 +1203,11 @@ impl Rc<dyn Any> {
11991203
/// ```
12001204
pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
12011205
if (*self).is::<T>() {
1202-
let ptr = self.ptr.cast::<RcBox<T>>();
1203-
forget(self);
1204-
Ok(Rc::from_inner(ptr))
1206+
unsafe {
1207+
let ptr = self.ptr.cast::<RcBox<T>>();
1208+
forget(self);
1209+
Ok(Rc::from_inner(ptr))
1210+
}
12051211
} else {
12061212
Err(self)
12071213
}
@@ -1474,8 +1480,10 @@ impl<T: ?Sized> Clone for Rc<T> {
14741480
/// ```
14751481
#[inline]
14761482
fn clone(&self) -> Rc<T> {
1477-
self.inner().inc_strong();
1478-
Self::from_inner(self.ptr)
1483+
unsafe {
1484+
self.inner().inc_strong();
1485+
Self::from_inner(self.ptr)
1486+
}
14791487
}
14801488
}
14811489

@@ -2225,11 +2233,14 @@ impl<T: ?Sized> Weak<T> {
22252233
#[stable(feature = "rc_weak", since = "1.4.0")]
22262234
pub fn upgrade(&self) -> Option<Rc<T>> {
22272235
let inner = self.inner()?;
2236+
22282237
if inner.strong() == 0 {
22292238
None
22302239
} else {
2231-
inner.inc_strong();
2232-
Some(Rc::from_inner(self.ptr))
2240+
unsafe {
2241+
inner.inc_strong();
2242+
Some(Rc::from_inner(self.ptr))
2243+
}
22332244
}
22342245
}
22352246

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.
@@ -526,7 +526,7 @@ impl<T> Arc<T> {
526526
weak: atomic::AtomicUsize::new(1),
527527
data,
528528
})?;
529-
Ok(Self::from_inner(Box::leak(x).into()))
529+
unsafe { Ok(Self::from_inner(Box::leak(x).into())) }
530530
}
531531

532532
/// Constructs a new `Arc` with uninitialized contents, returning an error
@@ -737,7 +737,7 @@ impl<T> Arc<mem::MaybeUninit<T>> {
737737
#[unstable(feature = "new_uninit", issue = "63291")]
738738
#[inline]
739739
pub unsafe fn assume_init(self) -> Arc<T> {
740-
Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast())
740+
unsafe { Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) }
741741
}
742742
}
743743

@@ -1327,7 +1327,7 @@ impl<T: ?Sized> Clone for Arc<T> {
13271327
abort();
13281328
}
13291329

1330-
Self::from_inner(self.ptr)
1330+
unsafe { Self::from_inner(self.ptr) }
13311331
}
13321332
}
13331333

@@ -1654,9 +1654,11 @@ impl Arc<dyn Any + Send + Sync> {
16541654
T: Any + Send + Sync + 'static,
16551655
{
16561656
if (*self).is::<T>() {
1657-
let ptr = self.ptr.cast::<ArcInner<T>>();
1658-
mem::forget(self);
1659-
Ok(Arc::from_inner(ptr))
1657+
unsafe {
1658+
let ptr = self.ptr.cast::<ArcInner<T>>();
1659+
mem::forget(self);
1660+
Ok(Arc::from_inner(ptr))
1661+
}
16601662
} else {
16611663
Err(self)
16621664
}
@@ -1880,7 +1882,7 @@ impl<T: ?Sized> Weak<T> {
18801882
// value can be initialized after `Weak` references have already been created. In that case, we
18811883
// expect to observe the fully initialized value.
18821884
match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
1883-
Ok(_) => return Some(Arc::from_inner(self.ptr)), // null checked above
1885+
Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above
18841886
Err(old) => n = old,
18851887
}
18861888
}

0 commit comments

Comments
 (0)