@@ -13,6 +13,7 @@ use http::header::Entry;
13
13
use http:: header:: ValueIter ;
14
14
use http:: header:: { self , HeaderMap , HeaderName , HeaderValue } ;
15
15
use http:: { Method , StatusCode , Version } ;
16
+ use smallvec:: { smallvec, smallvec_inline, SmallVec } ;
16
17
17
18
use crate :: body:: DecodedLength ;
18
19
#[ cfg( feature = "server" ) ]
@@ -29,7 +30,7 @@ use crate::proto::h1::{
29
30
use crate :: proto:: RequestHead ;
30
31
use crate :: proto:: { BodyLength , MessageHead , RequestLine } ;
31
32
32
- const MAX_HEADERS : usize = 100 ;
33
+ const DEFAULT_MAX_HEADERS : usize = 100 ;
33
34
const AVERAGE_HEADER_SIZE : usize = 30 ; // totally scientific
34
35
#[ cfg( feature = "server" ) ]
35
36
const MAX_URI_LEN : usize = ( u16:: MAX - 1 ) as usize ;
@@ -139,9 +140,17 @@ impl Http1Transaction for Server {
139
140
// but we *never* read any of it until after httparse has assigned
140
141
// values into it. By not zeroing out the stack memory, this saves
141
142
// a good ~5% on pipeline benchmarks.
142
- let mut headers_indices = [ MaybeUninit :: < HeaderIndices > :: uninit ( ) ; MAX_HEADERS ] ;
143
+ let mut headers_indices: SmallVec < [ MaybeUninit < HeaderIndices > ; DEFAULT_MAX_HEADERS ] > =
144
+ match ctx. h1_max_headers {
145
+ Some ( cap) => smallvec ! [ MaybeUninit :: uninit( ) ; cap] ,
146
+ None => smallvec_inline ! [ MaybeUninit :: uninit( ) ; DEFAULT_MAX_HEADERS ] ,
147
+ } ;
143
148
{
144
- let mut headers = [ MaybeUninit :: < httparse:: Header < ' _ > > :: uninit ( ) ; MAX_HEADERS ] ;
149
+ let mut headers: SmallVec < [ MaybeUninit < httparse:: Header < ' _ > > ; DEFAULT_MAX_HEADERS ] > =
150
+ match ctx. h1_max_headers {
151
+ Some ( cap) => smallvec ! [ MaybeUninit :: uninit( ) ; cap] ,
152
+ None => smallvec_inline ! [ MaybeUninit :: uninit( ) ; DEFAULT_MAX_HEADERS ] ,
153
+ } ;
145
154
trace ! ( bytes = buf. len( ) , "Request.parse" ) ;
146
155
let mut req = httparse:: Request :: new ( & mut [ ] ) ;
147
156
let bytes = buf. as_ref ( ) ;
@@ -966,9 +975,18 @@ impl Http1Transaction for Client {
966
975
967
976
// Loop to skip information status code headers (100 Continue, etc).
968
977
loop {
969
- let mut headers_indices = [ MaybeUninit :: < HeaderIndices > :: uninit ( ) ; MAX_HEADERS ] ;
978
+ let mut headers_indices: SmallVec < [ MaybeUninit < HeaderIndices > ; DEFAULT_MAX_HEADERS ] > =
979
+ match ctx. h1_max_headers {
980
+ Some ( cap) => smallvec ! [ MaybeUninit :: uninit( ) ; cap] ,
981
+ None => smallvec_inline ! [ MaybeUninit :: uninit( ) ; DEFAULT_MAX_HEADERS ] ,
982
+ } ;
970
983
let ( len, status, reason, version, headers_len) = {
971
- let mut headers = [ MaybeUninit :: < httparse:: Header < ' _ > > :: uninit ( ) ; MAX_HEADERS ] ;
984
+ let mut headers: SmallVec <
985
+ [ MaybeUninit < httparse:: Header < ' _ > > ; DEFAULT_MAX_HEADERS ] ,
986
+ > = match ctx. h1_max_headers {
987
+ Some ( cap) => smallvec ! [ MaybeUninit :: uninit( ) ; cap] ,
988
+ None => smallvec_inline ! [ MaybeUninit :: uninit( ) ; DEFAULT_MAX_HEADERS ] ,
989
+ } ;
972
990
trace ! ( bytes = buf. len( ) , "Response.parse" ) ;
973
991
let mut res = httparse:: Response :: new ( & mut [ ] ) ;
974
992
let bytes = buf. as_ref ( ) ;
@@ -1610,6 +1628,7 @@ mod tests {
1610
1628
cached_headers : & mut None ,
1611
1629
req_method : & mut method,
1612
1630
h1_parser_config : Default :: default ( ) ,
1631
+ h1_max_headers : None ,
1613
1632
h1_header_read_timeout : None ,
1614
1633
h1_header_read_timeout_fut : & mut None ,
1615
1634
h1_header_read_timeout_running : & mut false ,
@@ -1641,6 +1660,7 @@ mod tests {
1641
1660
cached_headers : & mut None ,
1642
1661
req_method : & mut Some ( crate :: Method :: GET ) ,
1643
1662
h1_parser_config : Default :: default ( ) ,
1663
+ h1_max_headers : None ,
1644
1664
h1_header_read_timeout : None ,
1645
1665
h1_header_read_timeout_fut : & mut None ,
1646
1666
h1_header_read_timeout_running : & mut false ,
@@ -1667,6 +1687,7 @@ mod tests {
1667
1687
cached_headers : & mut None ,
1668
1688
req_method : & mut None ,
1669
1689
h1_parser_config : Default :: default ( ) ,
1690
+ h1_max_headers : None ,
1670
1691
h1_header_read_timeout : None ,
1671
1692
h1_header_read_timeout_fut : & mut None ,
1672
1693
h1_header_read_timeout_running : & mut false ,
@@ -1691,6 +1712,7 @@ mod tests {
1691
1712
cached_headers : & mut None ,
1692
1713
req_method : & mut Some ( crate :: Method :: GET ) ,
1693
1714
h1_parser_config : Default :: default ( ) ,
1715
+ h1_max_headers : None ,
1694
1716
h1_header_read_timeout : None ,
1695
1717
h1_header_read_timeout_fut : & mut None ,
1696
1718
h1_header_read_timeout_running : & mut false ,
@@ -1717,6 +1739,7 @@ mod tests {
1717
1739
cached_headers : & mut None ,
1718
1740
req_method : & mut Some ( crate :: Method :: GET ) ,
1719
1741
h1_parser_config : Default :: default ( ) ,
1742
+ h1_max_headers : None ,
1720
1743
h1_header_read_timeout : None ,
1721
1744
h1_header_read_timeout_fut : & mut None ,
1722
1745
h1_header_read_timeout_running : & mut false ,
@@ -1747,6 +1770,7 @@ mod tests {
1747
1770
cached_headers : & mut None ,
1748
1771
req_method : & mut Some ( crate :: Method :: GET ) ,
1749
1772
h1_parser_config,
1773
+ h1_max_headers : None ,
1750
1774
h1_header_read_timeout : None ,
1751
1775
h1_header_read_timeout_fut : & mut None ,
1752
1776
h1_header_read_timeout_running : & mut false ,
@@ -1774,6 +1798,7 @@ mod tests {
1774
1798
cached_headers : & mut None ,
1775
1799
req_method : & mut Some ( crate :: Method :: GET ) ,
1776
1800
h1_parser_config : Default :: default ( ) ,
1801
+ h1_max_headers : None ,
1777
1802
h1_header_read_timeout : None ,
1778
1803
h1_header_read_timeout_fut : & mut None ,
1779
1804
h1_header_read_timeout_running : & mut false ,
@@ -1796,6 +1821,7 @@ mod tests {
1796
1821
cached_headers : & mut None ,
1797
1822
req_method : & mut None ,
1798
1823
h1_parser_config : Default :: default ( ) ,
1824
+ h1_max_headers : None ,
1799
1825
h1_header_read_timeout : None ,
1800
1826
h1_header_read_timeout_fut : & mut None ,
1801
1827
h1_header_read_timeout_running : & mut false ,
@@ -1839,6 +1865,7 @@ mod tests {
1839
1865
cached_headers : & mut None ,
1840
1866
req_method : & mut None ,
1841
1867
h1_parser_config : Default :: default ( ) ,
1868
+ h1_max_headers : None ,
1842
1869
h1_header_read_timeout : None ,
1843
1870
h1_header_read_timeout_fut : & mut None ,
1844
1871
h1_header_read_timeout_running : & mut false ,
@@ -1863,6 +1890,7 @@ mod tests {
1863
1890
cached_headers : & mut None ,
1864
1891
req_method : & mut None ,
1865
1892
h1_parser_config : Default :: default ( ) ,
1893
+ h1_max_headers : None ,
1866
1894
h1_header_read_timeout : None ,
1867
1895
h1_header_read_timeout_fut : & mut None ,
1868
1896
h1_header_read_timeout_running : & mut false ,
@@ -2096,6 +2124,7 @@ mod tests {
2096
2124
cached_headers: & mut None ,
2097
2125
req_method: & mut Some ( Method :: GET ) ,
2098
2126
h1_parser_config: Default :: default ( ) ,
2127
+ h1_max_headers: None ,
2099
2128
h1_header_read_timeout: None ,
2100
2129
h1_header_read_timeout_fut: & mut None ,
2101
2130
h1_header_read_timeout_running: & mut false ,
@@ -2120,6 +2149,7 @@ mod tests {
2120
2149
cached_headers : & mut None ,
2121
2150
req_method : & mut Some ( m) ,
2122
2151
h1_parser_config : Default :: default ( ) ,
2152
+ h1_max_headers : None ,
2123
2153
h1_header_read_timeout : None ,
2124
2154
h1_header_read_timeout_fut : & mut None ,
2125
2155
h1_header_read_timeout_running : & mut false ,
@@ -2144,6 +2174,7 @@ mod tests {
2144
2174
cached_headers : & mut None ,
2145
2175
req_method : & mut Some ( Method :: GET ) ,
2146
2176
h1_parser_config : Default :: default ( ) ,
2177
+ h1_max_headers : None ,
2147
2178
h1_header_read_timeout : None ,
2148
2179
h1_header_read_timeout_fut : & mut None ,
2149
2180
h1_header_read_timeout_running : & mut false ,
@@ -2663,6 +2694,7 @@ mod tests {
2663
2694
cached_headers : & mut None ,
2664
2695
req_method : & mut Some ( Method :: GET ) ,
2665
2696
h1_parser_config : Default :: default ( ) ,
2697
+ h1_max_headers : None ,
2666
2698
h1_header_read_timeout : None ,
2667
2699
h1_header_read_timeout_fut : & mut None ,
2668
2700
h1_header_read_timeout_running : & mut false ,
@@ -2681,6 +2713,143 @@ mod tests {
2681
2713
assert_eq ! ( parsed. head. headers[ "server" ] , "hello\t world" ) ;
2682
2714
}
2683
2715
2716
+ #[ test]
2717
+ fn parse_too_large_headers ( ) {
2718
+ fn gen_req_with_headers ( num : usize ) -> String {
2719
+ let mut req = String :: from ( "GET / HTTP/1.1\r \n " ) ;
2720
+ for i in 0 ..num {
2721
+ req. push_str ( & format ! ( "key{i}: val{i}\r \n " ) ) ;
2722
+ }
2723
+ req. push_str ( "\r \n " ) ;
2724
+ req
2725
+ }
2726
+ fn gen_resp_with_headers ( num : usize ) -> String {
2727
+ let mut req = String :: from ( "HTTP/1.1 200 OK\r \n " ) ;
2728
+ for i in 0 ..num {
2729
+ req. push_str ( & format ! ( "key{i}: val{i}\r \n " ) ) ;
2730
+ }
2731
+ req. push_str ( "\r \n " ) ;
2732
+ req
2733
+ }
2734
+ fn parse ( max_headers : Option < usize > , gen_size : usize , should_success : bool ) {
2735
+ {
2736
+ // server side
2737
+ let mut bytes = BytesMut :: from ( gen_req_with_headers ( gen_size) . as_str ( ) ) ;
2738
+ let result = Server :: parse (
2739
+ & mut bytes,
2740
+ ParseContext {
2741
+ cached_headers : & mut None ,
2742
+ req_method : & mut None ,
2743
+ h1_parser_config : Default :: default ( ) ,
2744
+ h1_max_headers : max_headers,
2745
+ h1_header_read_timeout : None ,
2746
+ h1_header_read_timeout_fut : & mut None ,
2747
+ h1_header_read_timeout_running : & mut false ,
2748
+ timer : Time :: Empty ,
2749
+ preserve_header_case : false ,
2750
+ #[ cfg( feature = "ffi" ) ]
2751
+ preserve_header_order : false ,
2752
+ h09_responses : false ,
2753
+ #[ cfg( feature = "ffi" ) ]
2754
+ on_informational : & mut None ,
2755
+ } ,
2756
+ ) ;
2757
+ if should_success {
2758
+ result. expect ( "parse ok" ) . expect ( "parse complete" ) ;
2759
+ } else {
2760
+ result. expect_err ( "parse should err" ) ;
2761
+ }
2762
+ }
2763
+ {
2764
+ // client side
2765
+ let mut bytes = BytesMut :: from ( gen_resp_with_headers ( gen_size) . as_str ( ) ) ;
2766
+ let result = Client :: parse (
2767
+ & mut bytes,
2768
+ ParseContext {
2769
+ cached_headers : & mut None ,
2770
+ req_method : & mut None ,
2771
+ h1_parser_config : Default :: default ( ) ,
2772
+ h1_max_headers : max_headers,
2773
+ h1_header_read_timeout : None ,
2774
+ h1_header_read_timeout_fut : & mut None ,
2775
+ h1_header_read_timeout_running : & mut false ,
2776
+ timer : Time :: Empty ,
2777
+ preserve_header_case : false ,
2778
+ #[ cfg( feature = "ffi" ) ]
2779
+ preserve_header_order : false ,
2780
+ h09_responses : false ,
2781
+ #[ cfg( feature = "ffi" ) ]
2782
+ on_informational : & mut None ,
2783
+ } ,
2784
+ ) ;
2785
+ if should_success {
2786
+ result. expect ( "parse ok" ) . expect ( "parse complete" ) ;
2787
+ } else {
2788
+ result. expect_err ( "parse should err" ) ;
2789
+ }
2790
+ }
2791
+ }
2792
+
2793
+ // check generator
2794
+ assert_eq ! (
2795
+ gen_req_with_headers( 0 ) ,
2796
+ String :: from( "GET / HTTP/1.1\r \n \r \n " )
2797
+ ) ;
2798
+ assert_eq ! (
2799
+ gen_req_with_headers( 1 ) ,
2800
+ String :: from( "GET / HTTP/1.1\r \n key0: val0\r \n \r \n " )
2801
+ ) ;
2802
+ assert_eq ! (
2803
+ gen_req_with_headers( 2 ) ,
2804
+ String :: from( "GET / HTTP/1.1\r \n key0: val0\r \n key1: val1\r \n \r \n " )
2805
+ ) ;
2806
+ assert_eq ! (
2807
+ gen_req_with_headers( 3 ) ,
2808
+ String :: from( "GET / HTTP/1.1\r \n key0: val0\r \n key1: val1\r \n key2: val2\r \n \r \n " )
2809
+ ) ;
2810
+
2811
+ // default max_headers is 100, so
2812
+ //
2813
+ // - less than or equal to 100, accepted
2814
+ //
2815
+ parse ( None , 0 , true ) ;
2816
+ parse ( None , 1 , true ) ;
2817
+ parse ( None , 50 , true ) ;
2818
+ parse ( None , 99 , true ) ;
2819
+ parse ( None , 100 , true ) ;
2820
+ //
2821
+ // - more than 100, rejected
2822
+ //
2823
+ parse ( None , 101 , false ) ;
2824
+ parse ( None , 102 , false ) ;
2825
+ parse ( None , 200 , false ) ;
2826
+
2827
+ // max_headers is 0, parser will reject any headers
2828
+ //
2829
+ // - without header, accepted
2830
+ //
2831
+ parse ( Some ( 0 ) , 0 , true ) ;
2832
+ //
2833
+ // - with header(s), rejected
2834
+ //
2835
+ parse ( Some ( 0 ) , 1 , false ) ;
2836
+ parse ( Some ( 0 ) , 100 , false ) ;
2837
+
2838
+ // max_headers is 200
2839
+ //
2840
+ // - less than or equal to 200, accepted
2841
+ //
2842
+ parse ( Some ( 200 ) , 0 , true ) ;
2843
+ parse ( Some ( 200 ) , 1 , true ) ;
2844
+ parse ( Some ( 200 ) , 100 , true ) ;
2845
+ parse ( Some ( 200 ) , 200 , true ) ;
2846
+ //
2847
+ // - more than 200, rejected
2848
+ //
2849
+ parse ( Some ( 200 ) , 201 , false ) ;
2850
+ parse ( Some ( 200 ) , 210 , false ) ;
2851
+ }
2852
+
2684
2853
#[ test]
2685
2854
fn test_write_headers_orig_case_empty_value ( ) {
2686
2855
let mut headers = HeaderMap :: new ( ) ;
@@ -2751,6 +2920,7 @@ mod tests {
2751
2920
cached_headers : & mut headers,
2752
2921
req_method : & mut None ,
2753
2922
h1_parser_config : Default :: default ( ) ,
2923
+ h1_max_headers : None ,
2754
2924
h1_header_read_timeout : None ,
2755
2925
h1_header_read_timeout_fut : & mut None ,
2756
2926
h1_header_read_timeout_running : & mut false ,
@@ -2795,6 +2965,7 @@ mod tests {
2795
2965
cached_headers : & mut headers,
2796
2966
req_method : & mut None ,
2797
2967
h1_parser_config : Default :: default ( ) ,
2968
+ h1_max_headers : None ,
2798
2969
h1_header_read_timeout : None ,
2799
2970
h1_header_read_timeout_fut : & mut None ,
2800
2971
h1_header_read_timeout_running : & mut false ,
0 commit comments