about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-06-21 17:11:28 -0700
committerRalf Jung <post@ralfj.de>2022-06-21 21:14:03 -0700
commit46b2454bad71b844ef5eb40860fb50131b6fe168 (patch)
tree4ae4ea928ef54c91fe2843a0dd51c2ffb992f1c4 /library/alloc/src
parentdc80ca78b6ec2b6bba02560470347433bcd0bb3c (diff)
downloadrust-46b2454bad71b844ef5eb40860fb50131b6fe168.tar.gz
rust-46b2454bad71b844ef5eb40860fb50131b6fe168.zip
clarify Arc::clone overflow check comment
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/sync.rs17
1 files changed, 9 insertions, 8 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 2670b15982a..24e849aab4c 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1355,15 +1355,16 @@ impl<T: ?Sized> Clone for Arc<T> {
         // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
         let old_size = self.inner().strong.fetch_add(1, Relaxed);
 
-        // However we need to guard against massive refcounts in case someone
-        // is `mem::forget`ing Arcs. If we don't do this the count can overflow
-        // and users will use-after free. We racily saturate to `isize::MAX` on
-        // the assumption that there aren't ~2 billion threads incrementing
-        // the reference count at once. This branch will never be taken in
-        // any realistic program.
+        // However we need to guard against massive refcounts in case someone is `mem::forget`ing
+        // Arcs. If we don't do this the count can overflow and users will use-after free. This
+        // branch will never be taken in any realistic program. We abort because such a program is
+        // incredibly degenerate, and we don't care to support it.
         //
-        // We abort because such a program is incredibly degenerate, and we
-        // don't care to support it.
+        // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`.
+        // But we do that check *after* having done the increment, so there is a chance here that
+        // the worst already happened and we actually do overflow the `usize` counter. However, that
+        // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment
+        // above and the `abort` below, which seems exceedingly unlikely.
         if old_size > MAX_REFCOUNT {
             abort();
         }