@@ -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
}
@@ -261,6 +264,7 @@ pub struct ParserConfig {
261
264
allow_multiple_spaces_in_response_status_delimiters : bool ,
262
265
ignore_invalid_headers_in_responses : bool ,
263
266
ignore_invalid_headers_in_requests : bool ,
267
+ max_header_list_size : Option < usize > ,
264
268
}
265
269
266
270
impl ParserConfig {
@@ -440,6 +444,18 @@ impl ParserConfig {
440
444
) -> Result < usize > {
441
445
response. parse_with_config_and_uninit_headers ( buf, self , headers)
442
446
}
447
+
448
+ /// Set the maximum size of all headers.
449
+ ///
450
+ /// The value is based on the size of unparsed header fields, including the
451
+ /// length of the name and value in octets, an overhead of 24 octets for
452
+ /// each header field and 8 octets for each additional whitespace.
453
+ ///
454
+ /// Default is unlimited.
455
+ pub fn max_header_list_size ( & mut self , val : usize ) -> & mut Self {
456
+ self . max_header_list_size = Some ( val) ;
457
+ self
458
+ }
443
459
}
444
460
445
461
/// A parsed Request.
@@ -513,6 +529,11 @@ impl<'h, 'b> Request<'h, 'b> {
513
529
newline ! ( bytes) ;
514
530
515
531
let len = orig_len - bytes. len ( ) ;
532
+ if let Some ( max) = config. max_header_list_size {
533
+ if len > max {
534
+ return Err ( Error :: HeadersTooLarge ) ;
535
+ }
536
+ }
516
537
let headers_len = complete ! ( parse_headers_iter_uninit(
517
538
& mut headers,
518
539
& mut bytes,
@@ -710,6 +731,11 @@ impl<'h, 'b> Response<'h, 'b> {
710
731
711
732
712
733
let len = orig_len - bytes. len ( ) ;
734
+ if let Some ( max) = config. max_header_list_size {
735
+ if len > max {
736
+ return Err ( Error :: HeadersTooLarge ) ;
737
+ }
738
+ }
713
739
let headers_len = complete ! ( parse_headers_iter_uninit(
714
740
& mut headers,
715
741
& mut bytes,
@@ -2498,4 +2524,40 @@ mod tests {
2498
2524
assert ! ( REQUEST . as_ptr( ) <= method. as_ptr( ) ) ;
2499
2525
assert ! ( method. as_ptr( ) <= buf_end) ;
2500
2526
}
2527
+
2528
+ #[ test]
2529
+ fn test_request_max_header_list_size ( ) {
2530
+ const REQUEST : & [ u8 ] = b"GET / HTTP/1.1\r \n Header: value\r \n \r \n " ;
2531
+
2532
+ let mut headers = [ EMPTY_HEADER ; 1 ] ;
2533
+ let mut request = Request :: new ( & mut headers[ ..] ) ;
2534
+
2535
+ let result = crate :: ParserConfig :: default ( )
2536
+ . max_header_list_size ( 10 )
2537
+ . parse_request ( & mut request, REQUEST ) ;
2538
+ assert_eq ! ( result, Err ( crate :: Error :: HeadersTooLarge ) ) ;
2539
+
2540
+ let result = crate :: ParserConfig :: default ( )
2541
+ . max_header_list_size ( 17 )
2542
+ . parse_request ( & mut request, REQUEST ) ;
2543
+ assert_eq ! ( result, Ok ( Status :: Complete ( REQUEST . len( ) ) ) ) ;
2544
+ }
2545
+
2546
+ #[ test]
2547
+ fn test_response_max_header_list_size ( ) {
2548
+ const RESPONSE : & [ u8 ] = b"HTTP/1.1 200 OK\r \n Header: value\r \n \r \n " ;
2549
+
2550
+ let mut headers = [ EMPTY_HEADER ; 1 ] ;
2551
+ let mut response = Response :: new ( & mut headers[ ..] ) ;
2552
+
2553
+ let result = crate :: ParserConfig :: default ( )
2554
+ . max_header_list_size ( 10 )
2555
+ . parse_response ( & mut response, RESPONSE ) ;
2556
+ assert_eq ! ( result, Err ( crate :: Error :: HeadersTooLarge ) ) ;
2557
+
2558
+ let result = crate :: ParserConfig :: default ( )
2559
+ . max_header_list_size ( 17 )
2560
+ . parse_response ( & mut response, RESPONSE ) ;
2561
+ assert_eq ! ( result, Ok ( Status :: Complete ( RESPONSE . len( ) ) ) ) ;
2562
+ }
2501
2563
}
0 commit comments