@@ -161,6 +161,8 @@ pub enum Error {
161
161
TooManyHeaders ,
162
162
/// Invalid byte in HTTP version.
163
163
Version ,
164
+ /// Unparsed headers are larger than the configured max size.
165
+ HeadersTooLarge ,
164
166
}
165
167
166
168
impl Error {
@@ -174,6 +176,7 @@ impl Error {
174
176
Error :: Token => "invalid token" ,
175
177
Error :: TooManyHeaders => "too many headers" ,
176
178
Error :: Version => "invalid HTTP version" ,
179
+ Error :: HeadersTooLarge => "headers too large" ,
177
180
}
178
181
}
179
182
}
@@ -262,6 +265,7 @@ pub struct ParserConfig {
262
265
allow_space_before_first_header_name : bool ,
263
266
ignore_invalid_headers_in_responses : bool ,
264
267
ignore_invalid_headers_in_requests : bool ,
268
+ max_header_list_size : Option < usize > ,
265
269
}
266
270
267
271
impl ParserConfig {
@@ -474,6 +478,18 @@ impl ParserConfig {
474
478
) -> Result < usize > {
475
479
response. parse_with_config_and_uninit_headers ( buf, self , headers)
476
480
}
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
+ }
477
493
}
478
494
479
495
/// A parsed Request.
@@ -547,6 +563,11 @@ impl<'h, 'b> Request<'h, 'b> {
547
563
newline ! ( bytes) ;
548
564
549
565
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
+ }
550
571
let headers_len = complete ! ( parse_headers_iter_uninit(
551
572
& mut headers,
552
573
& mut bytes,
@@ -745,6 +766,11 @@ impl<'h, 'b> Response<'h, 'b> {
745
766
746
767
747
768
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
+ }
748
774
let headers_len = complete ! ( parse_headers_iter_uninit(
749
775
& mut headers,
750
776
& mut bytes,
@@ -2558,7 +2584,7 @@ mod tests {
2558
2584
assert ! ( method. as_ptr( ) <= buf_end) ;
2559
2585
}
2560
2586
2561
- static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER : & [ u8 ] =
2587
+ static RESPONSE_WITH_SPACE_BEFORE_FIRST_HEADER : & [ u8 ] =
2562
2588
b"HTTP/1.1 200 OK\r \n Space-Before-Header: hello there\r \n \r \n " ;
2563
2589
2564
2590
#[ test]
@@ -2591,4 +2617,40 @@ mod tests {
2591
2617
assert_eq ! ( response. headers[ 0 ] . name, "Space-Before-Header" ) ;
2592
2618
assert_eq ! ( response. headers[ 0 ] . value, & b"hello there" [ ..] ) ;
2593
2619
}
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
+ }
2594
2656
}
0 commit comments