@@ -160,7 +160,7 @@ use core::cell::Cell;
160160use core:: cmp:: Ordering ;
161161use core:: fmt;
162162use core:: hash:: { Hasher , Hash } ;
163- use core:: intrinsics:: { assume, drop_in_place} ;
163+ use core:: intrinsics:: { assume, drop_in_place, abort } ;
164164use core:: marker:: { self , Unsize } ;
165165use core:: mem:: { self , align_of, size_of, align_of_val, size_of_val, forget} ;
166166use 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) ]
850859trait 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