Skip to content

Commit 1ffe345

Browse files
committed
make Rc mem::forget safe
1 parent ed49bad commit 1ffe345

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

src/liballoc/rc.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ use core::cell::Cell;
160160
use core::cmp::Ordering;
161161
use core::fmt;
162162
use core::hash::{Hasher, Hash};
163-
use core::intrinsics::{assume, drop_in_place};
163+
use core::intrinsics::{assume, drop_in_place, abort};
164164
use core::marker::{self, Unsize};
165165
use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget};
166166
use core::nonzero::NonZero;
@@ -846,6 +846,15 @@ impl<T: ?Sized+fmt::Debug> fmt::Debug for Weak<T> {
846846
}
847847
}
848848

849+
// NOTE: We checked_add here to deal with mem::forget safety. In particular
850+
// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
851+
// you can free the allocation while outstanding Rcs (or Weaks) exist.
852+
// We abort because this is such a degenerate scenario that we don't care about
853+
// what happens -- no real program should ever experience this.
854+
//
855+
// This should have negligible overhead since you don't actually need to
856+
// clone these much in Rust thanks to ownership and move-semantics.
857+
849858
#[doc(hidden)]
850859
trait RcBoxPtr<T: ?Sized> {
851860
fn inner(&self) -> &RcBox<T>;
@@ -854,7 +863,9 @@ trait RcBoxPtr<T: ?Sized> {
854863
fn strong(&self) -> usize { self.inner().strong.get() }
855864

856865
#[inline]
857-
fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
866+
fn inc_strong(&self) {
867+
self.inner().strong.set(self.strong().checked_add(1).unwrap_or_else(|| unsafe { abort() }));
868+
}
858869

859870
#[inline]
860871
fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
@@ -863,7 +874,9 @@ trait RcBoxPtr<T: ?Sized> {
863874
fn weak(&self) -> usize { self.inner().weak.get() }
864875

865876
#[inline]
866-
fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); }
877+
fn inc_weak(&self) {
878+
self.inner().weak.set(self.weak().checked_add(1).unwrap_or_else(|| unsafe { abort() }));
879+
}
867880

868881
#[inline]
869882
fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }

0 commit comments

Comments
 (0)