Skip to content

Commit ac7eb88

Browse files
Kriechipgjones
authored andcommitted
PUSH_PROMISE: fix promised stream id validation
https://tools.ietf.org/html/rfc7540#section-6.6 The promised stream identifier MUST be a valid choice for the next stream sent by the sender (see "new stream identifier" in Section 5.1.1). https://tools.ietf.org/html/rfc7540#section-5.1.1 Streams [...] initiated by the server MUST use even-numbered stream identifiers. https://tools.ietf.org/html/rfc7540#section-8.2 [...] servers MUST treat the receipt of a PUSH_PROMISE frame as a connection error
1 parent 1e14ced commit ac7eb88

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Release History
1212

1313
- Fixed padding parsing for ``PushPromiseFrame``.
1414
- Fixed unchecked frame length for ``PriorityFrame``. It now correctly raises ``InvalidFrameError``.
15+
- Fixed promised stream id parsing for ``PushPromiseFrame``.
1516

1617
**Other Changes**
1718

hyperframe/frame.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,12 @@ def parse_body(self, data):
485485
)
486486
self.body_len = len(data)
487487

488+
if self.promised_stream_id == 0 or self.promised_stream_id % 2 != 0:
489+
raise InvalidFrameError(
490+
"Invalid PUSH_PROMISE promised stream id: %s" %
491+
self.promised_stream_id
492+
)
493+
488494
if self.pad_length and self.pad_length >= self.body_len:
489495
raise InvalidPaddingError("Padding is too long.")
490496

test/test_frames.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,22 @@ def test_push_promise_frame_with_invalid_padding_fails_to_parse(self):
437437

438438
def test_push_promise_frame_with_no_length_parses(self):
439439
# Fixes issue with empty data frames raising InvalidPaddingError.
440-
f = PushPromiseFrame(1)
440+
f = PushPromiseFrame(1, 2)
441441
f.data = b''
442442
data = f.serialize()
443443

444444
new_frame = decode_frame(data)
445445
assert new_frame.data == b''
446446

447+
def test_push_promise_frame_invalid(self):
448+
data = PushPromiseFrame(1, 0).serialize()
449+
with pytest.raises(InvalidFrameError):
450+
decode_frame(data)
451+
452+
data = PushPromiseFrame(1, 3).serialize()
453+
with pytest.raises(InvalidFrameError):
454+
decode_frame(data)
455+
447456
def test_short_push_promise_errors(self):
448457
s = (
449458
b'\x00\x00\x0F\x05\x04\x00\x00\x00\x01' +

0 commit comments

Comments
 (0)