Skip to content

Commit 038d8d3

Browse files
committed
Reject unrepresentable body lengths in Frame.serialize()
1 parent 632e309 commit 038d8d3

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎CHANGELOG.rst‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ dev
1919

2020
**Bugfixes**
2121

22-
-
22+
- Reject oversized frame bodies in ``Frame.serialize()`` instead of silently
23+
truncating their 24-bit serialized length.
2324

2425
6.1.0 (2025-01-22)
2526
------------------

‎src/hyperframe/frame.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ def serialize(self) -> bytes:
159159
body = self.serialize_body()
160160
self.body_len = len(body)
161161

162+
if self.body_len > FRAME_MAX_ALLOWED_LEN:
163+
msg = f"Frame body exceeds maximum allowed length: {self.body_len} > {FRAME_MAX_ALLOWED_LEN}"
164+
raise InvalidFrameError(msg)
165+
162166
# Build the common frame header.
163167
# First, get the flags.
164168
flags = 0

‎tests/test_frames.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,29 @@ def test_cannot_parse_invalid_frame_header(self):
112112
with pytest.raises(InvalidFrameError):
113113
Frame.parse_frame_header(b'\x00\x00\x08\x00\x01\x00\x00\x00')
114114

115+
@pytest.mark.parametrize('frame_type', [DataFrame, ContinuationFrame])
116+
def test_serialize_maximum_frame_length(self, frame_type):
117+
f = frame_type(1, data=b'x' * 0xFFFFFF)
118+
wire = f.serialize()
119+
120+
assert wire[:3] == b'\xFF\xFF\xFF'
121+
assert f.body_len == len(wire) - 9 == 0xFFFFFF
122+
assert decode_frame(wire).data == f.data
123+
124+
@pytest.mark.parametrize('frame_type', [DataFrame, ContinuationFrame])
125+
@pytest.mark.parametrize('body_length', [0x1000000, 0x1000001])
126+
def test_serialize_rejects_unrepresentable_frame_length(self, frame_type, body_length):
127+
f = frame_type(1, data=b'x' * body_length)
128+
129+
with pytest.raises(InvalidFrameError):
130+
f.serialize()
131+
132+
def test_serialize_length_limit_includes_padding_length_field(self):
133+
f = DataFrame(1, data=b'x' * 0xFFFFFF, flags=['PADDED'])
134+
135+
with pytest.raises(InvalidFrameError):
136+
f.serialize()
137+
115138

116139
class TestDataFrame:
117140
payload = b'\x00\x00\x08\x00\x01\x00\x00\x00\x01testdata'

0 commit comments

Comments
 (0)