@@ -161,6 +161,8 @@ pub enum Error {
161161 TooManyHeaders ,
162162 /// Invalid byte in HTTP version.
163163 Version ,
164+ /// Unparsed headers are larger than the configured max size.
165+ HeadersTooLarge ,
164166}
165167
166168impl Error {
@@ -174,6 +176,7 @@ impl Error {
174176 Error :: Token => "invalid token" ,
175177 Error :: TooManyHeaders => "too many headers" ,
176178 Error :: Version => "invalid HTTP version" ,
179+ Error :: HeadersTooLarge => "headers too large" ,
177180 }
178181 }
179182}
@@ -262,6 +265,7 @@ pub struct ParserConfig {
262265 allow_space_before_first_header_name : bool ,
263266 ignore_invalid_headers_in_responses : bool ,
264267 ignore_invalid_headers_in_requests : bool ,
268+ max_header_list_size : Option < usize > ,
265269}
266270
267271impl ParserConfig {
@@ -474,6 +478,18 @@ impl ParserConfig {
474478 ) -> Result < usize > {
475479 response. parse_with_config_and_uninit_headers ( buf, self , headers)
476480 }
481+
482+ /// Set the maximum size of all headers.
483+ ///
484+ /// The value is based on the size of unparsed header fields, including the
485+ /// length of the name and value in octets, an overhead of 24 octets for
486+ /// each header field and 8 octets for each additional whitespace.
487+ ///
488+ /// Default is unlimited.
489+ pub fn max_header_list_size ( & mut self , val : usize ) -> & mut Self {
490+ self . max_header_list_size = Some ( val) ;
491+ self
492+ }
477493}
478494
479495/// A parsed Request.
@@ -547,6 +563,11 @@ impl<'h, 'b> Request<'h, 'b> {
547563 newline ! ( bytes) ;
548564
549565 let len = orig_len - bytes. len ( ) ;
566+ if let Some ( max) = config. max_header_list_size {
567+ if len > max {
568+ return Err ( Error :: HeadersTooLarge ) ;
569+ }
570+ }
550571 let headers_len = complete ! ( parse_headers_iter_uninit(
551572 & mut headers,
552573 & mut bytes,
@@ -745,6 +766,11 @@ impl<'h, 'b> Response<'h, 'b> {
745766
746767
747768 let len = orig_len - bytes. len ( ) ;
769+ if let Some ( max) = config. max_header_list_size {
770+ if len > max {
771+ return Err ( Error :: HeadersTooLarge ) ;
772+ }
773+ }
748774 let headers_len = complete ! ( parse_headers_iter_uninit(
749775 & mut headers,
750776 & mut bytes,
@@ -2558,7 +2584,7 @@ mod tests {
25582584 assert ! ( method. as_ptr( ) <= buf_end) ;
25592585 }
25602586
2561- static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER : & [ u8 ] =
2587+ static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER : & [ u8 ] =
25622588 b"HTTP/1.1 200 OK\r \n Space-Before-Header: hello there\r \n \r \n " ;
25632589
25642590 #[ test]
@@ -2591,4 +2617,40 @@ mod tests {
25912617 assert_eq ! ( response. headers[ 0 ] . name, "Space-Before-Header" ) ;
25922618 assert_eq ! ( response. headers[ 0 ] . value, & b"hello there" [ ..] ) ;
25932619 }
2620+
2621+ #[ test]
2622+ fn test_request_max_header_list_size ( ) {
2623+ const REQUEST : & [ u8 ] = b"GET / HTTP/1.1\r \n Header: value\r \n \r \n " ;
2624+
2625+ let mut headers = [ EMPTY_HEADER ; 1 ] ;
2626+ let mut request = Request :: new ( & mut headers[ ..] ) ;
2627+
2628+ let result = crate :: ParserConfig :: default ( )
2629+ . max_header_list_size ( 10 )
2630+ . parse_request ( & mut request, REQUEST ) ;
2631+ assert_eq ! ( result, Err ( crate :: Error :: HeadersTooLarge ) ) ;
2632+
2633+ let result = crate :: ParserConfig :: default ( )
2634+ . max_header_list_size ( 17 )
2635+ . parse_request ( & mut request, REQUEST ) ;
2636+ assert_eq ! ( result, Ok ( Status :: Complete ( REQUEST . len( ) ) ) ) ;
2637+ }
2638+
2639+ #[ test]
2640+ fn test_response_max_header_list_size ( ) {
2641+ const RESPONSE : & [ u8 ] = b"HTTP/1.1 200 OK\r \n Header: value\r \n \r \n " ;
2642+
2643+ let mut headers = [ EMPTY_HEADER ; 1 ] ;
2644+ let mut response = Response :: new ( & mut headers[ ..] ) ;
2645+
2646+ let result = crate :: ParserConfig :: default ( )
2647+ . max_header_list_size ( 10 )
2648+ . parse_response ( & mut response, RESPONSE ) ;
2649+ assert_eq ! ( result, Err ( crate :: Error :: HeadersTooLarge ) ) ;
2650+
2651+ let result = crate :: ParserConfig :: default ( )
2652+ . max_header_list_size ( 17 )
2653+ . parse_response ( & mut response, RESPONSE ) ;
2654+ assert_eq ! ( result, Ok ( Status :: Complete ( RESPONSE . len( ) ) ) ) ;
2655+ }
25942656}
0 commit comments