Skip to content

Commit 87e3d6f

Browse files
authored
Raise a ProtocolError if we receive data before headers (#1230)
1 parent 49bed1c commit 87e3d6f

File tree

3 files changed

+21
-0
lines changed

3 files changed

+21
-0
lines changed

HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ API Changes (Backward-Incompatible)
1111
- Support for Python 3.4 has been removed.
1212
- Support for Python 3.5 has been removed.
1313
- Support for PyPy (Python 2.7 compatible) has been removed.
14+
- Receiving DATA before HEADERS now raises a ProtocolError (see https://tools.ietf.org/html/rfc7540#section-8.1)
1415

1516

1617
3.2.0 (2020-02-08)

h2/stream.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ def data_received(self, previous_state):
198198
"""
199199
Fires when data is received.
200200
"""
201+
if not self.headers_received:
202+
raise ProtocolError("cannot receive data before headers")
201203
event = DataReceived()
202204
event.stream_id = self.stream_id
203205
return [event]

test/test_invalid_frame_sequences.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class TestInvalidFrameSequences(object):
3131
('server', 'fake-serv/0.1.0')
3232
]
3333
server_config = h2.config.H2Configuration(client_side=False)
34+
client_config = h2.config.H2Configuration(client_side=True)
3435

3536
def test_cannot_send_on_closed_stream(self):
3637
"""
@@ -279,6 +280,23 @@ def test_invalid_frame_headers_are_protocol_errors(self, frame_factory):
279280

280281
assert "Stream ID must be non-zero" in str(e.value)
281282

283+
def test_data_before_headers(self, frame_factory):
284+
"""
285+
When data frames are received before headers
286+
they cause ProtocolErrors to be raised.
287+
"""
288+
c = h2.connection.H2Connection(config=self.client_config)
289+
c.initiate_connection()
290+
# transition stream into OPEN
291+
c.send_headers(1, self.example_request_headers)
292+
293+
f = frame_factory.build_data_frame(b"hello")
294+
295+
with pytest.raises(h2.exceptions.ProtocolError) as e:
296+
c.receive_data(f.serialize())
297+
298+
assert "cannot receive data before headers" in str(e.value)
299+
282300
def test_get_stream_reset_event_on_auto_reset(self, frame_factory):
283301
"""
284302
When hyper-h2 resets a stream automatically, a StreamReset event fires.

0 commit comments

Comments
 (0)