@@ -1989,3 +1989,61 @@ async fn reclaim_reserved_capacity() {
19891989
19901990 join ( mock, h2) . await ;
19911991}
1992+
1993+ // ==== abusive window updates ====
1994+
1995+ #[ tokio:: test]
1996+ async fn too_many_window_update_resets_causes_go_away ( ) {
1997+ h2_support:: trace_init!( ) ;
1998+ let ( io, mut client) = mock:: new ( ) ;
1999+
2000+ let client = async move {
2001+ let settings = client. assert_server_handshake ( ) . await ;
2002+ assert_default_settings ! ( settings) ;
2003+ for s in ( 1 ..21 ) . step_by ( 2 ) {
2004+ client
2005+ . send_frame (
2006+ frames:: headers ( s)
2007+ . request ( "GET" , "https://example.com/" )
2008+ . eos ( ) ,
2009+ )
2010+ . await ;
2011+ // send a bunch of bad window updates before any headers
2012+ client
2013+ . send_frame ( frames:: window_update ( s, u32:: MAX - 2 ) )
2014+ . await ;
2015+ client. recv_frame ( frames:: reset ( s) . flow_control ( ) ) . await ;
2016+ }
2017+
2018+ client
2019+ . send_frame (
2020+ frames:: headers ( 21 )
2021+ . request ( "GET" , "https://example.com/" )
2022+ . eos ( ) ,
2023+ )
2024+ . await ;
2025+ // send a bunch of bad window updates before any headers
2026+ client
2027+ . send_frame ( frames:: window_update ( 21 , u32:: MAX - 2 ) )
2028+ . await ;
2029+ client
2030+ . recv_frame ( frames:: go_away ( 21 ) . calm ( ) . data ( "too_many_internal_resets" ) )
2031+ . await ;
2032+ } ;
2033+ let srv = async move {
2034+ let mut conn = server:: Builder :: new ( )
2035+ . max_local_error_reset_streams ( Some ( 10 ) )
2036+ . handshake :: < _ , Bytes > ( io)
2037+ . await
2038+ . unwrap ( ) ;
2039+ for _ in ( 1 ..21 ) . step_by ( 2 ) {
2040+ let ( _, _) = conn. next ( ) . await . unwrap ( ) . unwrap ( ) ;
2041+ }
2042+ let err = conn. next ( ) . await . unwrap ( ) . unwrap_err ( ) ;
2043+ assert ! ( err. is_go_away( ) ) ;
2044+ assert ! ( err. is_library( ) ) ;
2045+ assert_eq ! ( err. reason( ) , Some ( Reason :: ENHANCE_YOUR_CALM ) ) ;
2046+ } ;
2047+
2048+ join ( srv, client) . await ;
2049+ }
0 commit comments