@@ -51,8 +51,16 @@ mod tests;
5151///
5252/// Going above this limit will abort your program (although not
5353/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
54+ /// Trying to go above it might call a `panic` (if not actually going above it).
55+ ///
56+ /// This is a global invariant, and also applies when using a compare-exchange loop.
57+ ///
58+ /// See comment in `Arc::clone`.
5459const MAX_REFCOUNT : usize = ( isize:: MAX ) as usize ;
5560
61+ /// The error in case either counter reaches above `MAX_REFCOUNT`, and we can `panic` safely.
62+ const INTERNAL_OVERFLOW_ERROR : & str = "Arc counter overflow" ;
63+
5664#[ cfg( not( sanitize = "thread" ) ) ]
5765macro_rules! acquire {
5866 ( $x: expr) => {
@@ -1104,6 +1112,9 @@ impl<T: ?Sized> Arc<T> {
11041112 continue ;
11051113 }
11061114
1115+ // We can't allow the refcount to increase much past `MAX_REFCOUNT`.
1116+ assert ! ( cur <= MAX_REFCOUNT , "{}" , INTERNAL_OVERFLOW_ERROR ) ;
1117+
11071118 // NOTE: this code currently ignores the possibility of overflow
11081119 // into usize::MAX; in general both Rc and Arc need to be adjusted
11091120 // to deal with overflow.
@@ -1519,6 +1530,11 @@ impl<T: ?Sized> Clone for Arc<T> {
15191530 // the worst already happened and we actually do overflow the `usize` counter. However, that
15201531 // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment
15211532 // above and the `abort` below, which seems exceedingly unlikely.
1533+ //
1534+ // This is a global invariant, and also applies when using a compare-exchange loop to increment
1535+ // counters in other methods.
1536+ // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop,
1537+ // and then overflow using a few `fetch_add`s.
15221538 if old_size > MAX_REFCOUNT {
15231539 abort ( ) ;
15241540 }
@@ -2180,9 +2196,7 @@ impl<T: ?Sized> Weak<T> {
21802196 return None ;
21812197 }
21822198 // See comments in `Arc::clone` for why we do this (for `mem::forget`).
2183- if n > MAX_REFCOUNT {
2184- abort ( ) ;
2185- }
2199+ assert ! ( n <= MAX_REFCOUNT , "{}" , INTERNAL_OVERFLOW_ERROR ) ;
21862200 Some ( n + 1 )
21872201 } )
21882202 . ok ( )
0 commit comments