@@ -160,7 +160,7 @@ use core::cell::Cell;
160
160
use core:: cmp:: Ordering ;
161
161
use core:: fmt;
162
162
use core:: hash:: { Hasher , Hash } ;
163
- use core:: intrinsics:: { assume, drop_in_place} ;
163
+ use core:: intrinsics:: { assume, drop_in_place, abort } ;
164
164
use core:: marker:: { self , Unsize } ;
165
165
use core:: mem:: { self , align_of, size_of, align_of_val, size_of_val, forget} ;
166
166
use core:: nonzero:: NonZero ;
@@ -846,6 +846,15 @@ impl<T: ?Sized+fmt::Debug> fmt::Debug for Weak<T> {
846
846
}
847
847
}
848
848
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
+
849
858
#[ doc( hidden) ]
850
859
trait RcBoxPtr < T : ?Sized > {
851
860
fn inner ( & self ) -> & RcBox < T > ;
@@ -854,7 +863,9 @@ trait RcBoxPtr<T: ?Sized> {
854
863
fn strong ( & self ) -> usize { self . inner ( ) . strong . get ( ) }
855
864
856
865
#[ 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
+ }
858
869
859
870
#[ inline]
860
871
fn dec_strong ( & self ) { self . inner ( ) . strong . set ( self . strong ( ) - 1 ) ; }
@@ -863,7 +874,9 @@ trait RcBoxPtr<T: ?Sized> {
863
874
fn weak ( & self ) -> usize { self . inner ( ) . weak . get ( ) }
864
875
865
876
#[ 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
+ }
867
880
868
881
#[ inline]
869
882
fn dec_weak ( & self ) { self . inner ( ) . weak . set ( self . weak ( ) - 1 ) ; }
0 commit comments