@@ -19,18 +19,24 @@ class TestInvalidContentLengths:
1919 peer is not valid.
2020 """
2121
22- example_request_headers = [
22+ example_request_headers_without_content_length = [
2323 (":authority" , "example.com" ),
2424 (":path" , "/" ),
2525 (":scheme" , "https" ),
2626 (":method" , "POST" ),
27+ ]
28+ example_request_headers = [
29+ * example_request_headers_without_content_length ,
2730 ("content-length" , "15" ),
2831 ]
29- example_request_headers_bytes = [
32+ example_request_headers_bytes_without_content_length = [
3033 (b":authority" , b"example.com" ),
3134 (b":path" , b"/" ),
3235 (b":scheme" , b"https" ),
3336 (b":method" , b"POST" ),
37+ ]
38+ example_request_headers_bytes = [
39+ * example_request_headers_bytes_without_content_length ,
3440 (b"content-length" , b"15" ),
3541 ]
3642 example_response_headers = [
@@ -39,6 +45,75 @@ class TestInvalidContentLengths:
3945 ]
4046 server_config = h2 .config .H2Configuration (client_side = False )
4147
48+ @pytest .mark .parametrize (
49+ "request_headers" ,
50+ [
51+ example_request_headers_without_content_length ,
52+ example_request_headers_bytes_without_content_length ,
53+ ],
54+ )
55+ def test_duplicate_matching_content_lengths (self , frame_factory , request_headers ) -> None :
56+ """
57+ Remote peers sending duplicate matching content-length fields are
58+ accepted.
59+ """
60+ c = h2 .connection .H2Connection (config = self .server_config )
61+ c .initiate_connection ()
62+ c .receive_data (frame_factory .preamble ())
63+ c .clear_outbound_data_buffer ()
64+
65+ headers = frame_factory .build_headers_frame (
66+ headers = [
67+ * request_headers ,
68+ ("content-length" , "15" ),
69+ ("content-length" , "15" ),
70+ ],
71+ )
72+ data = frame_factory .build_data_frame (
73+ data = b"\x01 " * 15 ,
74+ flags = ["END_STREAM" ],
75+ )
76+
77+ events = c .receive_data (headers .serialize () + data .serialize ())
78+
79+ assert isinstance (events [0 ], h2 .events .RequestReceived )
80+ assert isinstance (events [1 ], h2 .events .DataReceived )
81+ assert isinstance (events [2 ], h2 .events .StreamEnded )
82+ assert c .data_to_send () == b""
83+
84+ @pytest .mark .parametrize (
85+ "request_headers" ,
86+ [
87+ example_request_headers_without_content_length ,
88+ example_request_headers_bytes_without_content_length ,
89+ ],
90+ )
91+ def test_duplicate_conflicting_content_lengths (self , frame_factory , request_headers ) -> None :
92+ """
93+ Remote peers sending duplicate conflicting content-length fields cause
94+ Protocol Errors.
95+ """
96+ c = h2 .connection .H2Connection (config = self .server_config )
97+ c .initiate_connection ()
98+ c .receive_data (frame_factory .preamble ())
99+ c .clear_outbound_data_buffer ()
100+
101+ headers = frame_factory .build_headers_frame (
102+ headers = [
103+ * request_headers ,
104+ ("content-length" , "15" ),
105+ ("content-length" , "16" ),
106+ ],
107+ )
108+ with pytest .raises (h2 .exceptions .ProtocolError ):
109+ c .receive_data (headers .serialize ())
110+
111+ expected_frame = frame_factory .build_goaway_frame (
112+ last_stream_id = 1 ,
113+ error_code = h2 .errors .ErrorCodes .PROTOCOL_ERROR ,
114+ )
115+ assert c .data_to_send () == expected_frame .serialize ()
116+
42117 @pytest .mark .parametrize ("request_headers" , [example_request_headers , example_request_headers_bytes ])
43118 def test_too_much_data (self , frame_factory , request_headers ) -> None :
44119 """
0 commit comments