File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -2133,12 +2133,16 @@ impl<T> Extend<(Option<HeaderName>, T)> for HeaderMap<T> {
21332133 // Reserve the entire hint lower bound if the map is empty.
21342134 // Otherwise reserve half the hint (rounded up), so the map
21352135 // will only resize twice in the worst case.
2136- let reserve = if self . is_empty ( ) {
2136+ let hint = if self . is_empty ( ) {
21372137 iter. size_hint ( ) . 0
21382138 } else {
21392139 ( iter. size_hint ( ) . 0 + 1 ) / 2
21402140 } ;
21412141
2142+ // Clamp the hint so an over-estimate cannot overflow `reserve`.
2143+ let max_reserve = usable_capacity ( MAX_SIZE ) . saturating_sub ( self . entries . len ( ) ) ;
2144+ let reserve = hint. min ( max_reserve) ;
2145+
21422146 self . reserve ( reserve) ;
21432147
21442148 // The structure of this is a bit weird, but it is mostly to make the
@@ -2189,12 +2193,16 @@ impl<T> Extend<(HeaderName, T)> for HeaderMap<T> {
21892193 // will only resize twice in the worst case.
21902194 let iter = iter. into_iter ( ) ;
21912195
2192- let reserve = if self . is_empty ( ) {
2196+ let hint = if self . is_empty ( ) {
21932197 iter. size_hint ( ) . 0
21942198 } else {
21952199 ( iter. size_hint ( ) . 0 + 1 ) / 2
21962200 } ;
21972201
2202+ // Clamp the hint so an over-estimate cannot overflow `reserve`.
2203+ let max_reserve = usable_capacity ( MAX_SIZE ) . saturating_sub ( self . entries . len ( ) ) ;
2204+ let reserve = hint. min ( max_reserve) ;
2205+
21982206 self . reserve ( reserve) ;
21992207
22002208 for ( k, v) in iter {
Original file line number Diff line number Diff line change @@ -55,6 +55,23 @@ fn with_capacity_overflow() {
5555 HeaderMap :: < u32 > :: with_capacity ( 24_577 ) ;
5656}
5757
58+ #[ test]
59+ fn extend_size_hint_above_capacity ( ) {
60+ // A `HeaderMap` may hold more values than the table can index when many
61+ // values are appended under one name, so an exact size hint can exceed the
62+ // largest `reserve` request. Extending must not panic in that case.
63+ let name = HeaderName :: from_static ( "h" ) ;
64+ let value = HeaderValue :: from_static ( "0" ) ;
65+ let pairs: Vec < ( HeaderName , HeaderValue ) > =
66+ std:: iter:: repeat_with ( || ( name. clone ( ) , value. clone ( ) ) )
67+ . take ( 24_577 )
68+ . collect ( ) ;
69+
70+ let map = HeaderMap :: from_iter ( pairs) ;
71+ assert_eq ! ( map. len( ) , 24_577 ) ;
72+ assert_eq ! ( map. keys_len( ) , 1 ) ;
73+ }
74+
5875#[ test]
5976#[ should_panic]
6077fn reserve_overflow ( ) {
You can’t perform that action at this time.
0 commit comments