Skip to content

Commit 0184b40

Browse files
committed
Make sure to never create a reference to an invalid CcOnHeap
1 parent 08f921f commit 0184b40

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

src/cc.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::cell::UnsafeCell;
33
use std::marker::PhantomData;
44
use std::mem::{self, MaybeUninit};
55
use std::ops::Deref;
6-
use std::ptr::{self, drop_in_place, NonNull};
6+
use std::ptr::{self, addr_of, drop_in_place, NonNull};
77
use std::rc::Rc;
88
#[cfg(feature = "nightly")]
99
use std::{
@@ -63,7 +63,7 @@ impl<T: Trace + 'static> Cc<T> {
6363
#[cfg(feature = "auto-collect")]
6464
super::trigger_collection();
6565

66-
let mut invalid = CcOnHeap::<T>::new_invalid();
66+
let mut invalid: NonNull<CcOnHeap<MaybeUninit<T>>> = CcOnHeap::<T>::new_invalid();
6767
let cc = Cc {
6868
inner: invalid.cast(),
6969
_phantom: PhantomData,
@@ -75,7 +75,7 @@ impl<T: Trace + 'static> Cc<T> {
7575
}
7676

7777
// Set valid
78-
cc.inner().counter_marker().mark(Mark::NonMarked);
78+
cc.counter_marker().mark(Mark::NonMarked);
7979

8080
// Return cc, since it is now valid
8181
cc
@@ -97,7 +97,7 @@ impl<T: Trace + 'static> Cc<T> {
9797
assert!(self.is_unique(), "Cc<_> is not unique");
9898

9999
assert!(
100-
!self.inner().counter_marker().is_traced_or_invalid(),
100+
!self.counter_marker().is_traced_or_invalid(),
101101
"Cc<_> is being used by the collector and inner value cannot be taken out (this might have happen inside Trace, Finalize or Drop implementations)."
102102
);
103103

@@ -196,7 +196,7 @@ impl<T: ?Sized + Trace + 'static> Cc<T> {
196196

197197
#[inline]
198198
pub fn strong_count(&self) -> u32 {
199-
self.inner().counter_marker().counter()
199+
self.counter_marker().counter()
200200
}
201201

202202
#[inline]
@@ -206,7 +206,7 @@ impl<T: ?Sized + Trace + 'static> Cc<T> {
206206

207207
#[inline]
208208
pub fn is_valid(&self) -> bool {
209-
self.inner().is_valid()
209+
self.counter_marker().is_valid()
210210
}
211211

212212
#[cfg(feature = "finalization")]
@@ -215,28 +215,28 @@ impl<T: ?Sized + Trace + 'static> Cc<T> {
215215
pub fn finalize_again(&mut self) {
216216
assert!(state(|state| !state.is_collecting()), "Cannot schedule finalization again while collecting");
217217

218-
self.inner().counter_marker().set_finalized(false);
218+
self.counter_marker().set_finalized(false);
219219
}
220220

221221
#[cfg(feature = "finalization")]
222222
#[inline]
223223
pub fn already_finalized(&self) -> bool {
224-
!self.inner().counter_marker().needs_finalization()
224+
!self.counter_marker().needs_finalization()
225225
}
226226

227-
/// Note: don't access self.inner().elem if CcOnHeap is not valid!
228227
#[inline(always)]
229-
fn inner(&self) -> &CcOnHeap<T> {
230-
// If Cc is alive then we can always access the underlying CcOnHeap
231-
unsafe { self.inner.as_ref() }
228+
fn counter_marker(&self) -> &CounterMarker {
229+
// SAFETY: It's always safe to access the counter_marker if we're not dereferencing anything else
230+
unsafe {
231+
&*addr_of!((*self.inner.as_ptr()).counter_marker)
232+
}
232233
}
233234

234-
/// Note: don't access self.inner_mut().elem if CcOnHeap is not valid!
235+
/// Note: don't call if CcOnHeap is not valid!
235236
#[inline(always)]
236-
// Not currently used
237-
fn _inner_mut(&mut self) -> &mut CcOnHeap<T> {
238-
// If Cc is alive then we can always access the underlying CcOnHeap
239-
unsafe { self.inner.as_mut() }
237+
fn inner(&self) -> &CcOnHeap<T> {
238+
// SAFETY: since Cc is alive and the underlying CcOnHeap is valid then we can access it
239+
unsafe { self.inner.as_ref() }
240240
}
241241
}
242242

@@ -248,7 +248,7 @@ impl<T: ?Sized + Trace + 'static> Clone for Cc<T> {
248248
panic!("Cannot clone while tracing!");
249249
}
250250

251-
if self.inner().counter_marker().increment_counter().is_err() {
251+
if self.counter_marker().increment_counter().is_err() {
252252
panic!("Too many references has been created to a single Cc");
253253
}
254254

@@ -283,7 +283,7 @@ impl<T: ?Sized + Trace + 'static> Deref for Cc<T> {
283283

284284
impl<T: ?Sized + Trace + 'static> Drop for Cc<T> {
285285
fn drop(&mut self) {
286-
let counter_marker = self.inner().counter_marker();
286+
let counter_marker = self.counter_marker();
287287

288288
// Always decrement the counter
289289
let res = counter_marker.decrement_counter();
@@ -295,7 +295,7 @@ impl<T: ?Sized + Trace + 'static> Drop for Cc<T> {
295295
return;
296296
}
297297

298-
if self.strong_count() == 0 {
298+
if counter_marker.counter() == 0 {
299299
// Only us have a pointer to this allocation, deallocate!
300300

301301
remove_from_list(self.inner.cast());
@@ -312,7 +312,7 @@ impl<T: ?Sized + Trace + 'static> Drop for Cc<T> {
312312
counter_marker.set_finalized(true);
313313

314314
self.inner().get_elem().finalize();
315-
self.strong_count() == 0
315+
counter_marker.counter() == 0
316316
// _finalizing_guard is dropped here, resetting state.finalizing
317317
} else {
318318
true

0 commit comments

Comments
 (0)