File tree Expand file tree Collapse file tree 1 file changed +26
-0
lines changed Expand file tree Collapse file tree 1 file changed +26
-0
lines changed Original file line number Diff line number Diff line change @@ -609,7 +609,13 @@ impl<T> LinkedList<T> {
609609 length : len - at
610610 } ;
611611
612+ // Swap split_node.next with list_head (which is None), nulling out split_node.next,
613+ // as it is the new tail.
612614 mem:: swap ( & mut split_node. resolve ( ) . unwrap ( ) . next , & mut splitted_list. list_head ) ;
615+ // Null out list_head.prev. Note this `unwrap` won't fail because if at == len
616+ // we already branched out at the top of the fn to return the empty list.
617+ splitted_list. list_head . as_mut ( ) . unwrap ( ) . prev = Rawlink :: none ( ) ;
618+ // Fix the tail ptr
613619 self . list_tail = split_node;
614620 self . length = at;
615621
@@ -1075,6 +1081,26 @@ mod tests {
10751081 }
10761082 }
10771083
1084+ #[ test]
1085+ fn test_26021 ( ) {
1086+ use std:: iter:: ExactSizeIterator ;
1087+ // There was a bug in split_off that failed to null out the RHS's head's prev ptr.
1088+ // This caused the RHS's dtor to walk up into the LHS at drop and delete all of
1089+ // its nodes.
1090+ //
1091+ // https://github.com/rust-lang/rust/issues/26021
1092+ let mut v1 = LinkedList :: new ( ) ;
1093+ v1. push_front ( 1u8 ) ;
1094+ v1. push_front ( 1u8 ) ;
1095+ v1. push_front ( 1u8 ) ;
1096+ v1. push_front ( 1u8 ) ;
1097+ let _ = v1. split_off ( 3 ) ; // Dropping this now should not cause laundry consumption
1098+ assert_eq ! ( v1. len( ) , 3 ) ;
1099+
1100+ assert_eq ! ( v1. iter( ) . len( ) , 3 ) ;
1101+ assert_eq ! ( v1. iter( ) . collect:: <Vec <_>>( ) . len( ) , 3 ) ;
1102+ }
1103+
10781104 #[ cfg( test) ]
10791105 fn fuzz_test ( sz : i32 ) {
10801106 let mut m: LinkedList < _ > = LinkedList :: new ( ) ;
You can’t perform that action at this time.
0 commit comments