Skip to content

Commit 7b0db7e

Browse files
committed
setting identifier truncating: add comments, tests, and changelog
1 parent dd71c3b commit 7b0db7e

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Release History
44
dev
55
---
66

7+
**API Changes (Backward Compatible)**
8+
9+
- Setting Identifier are now correctly serialized as 16-bit values, instead of 8-bit.
10+
711
**API Changes (Backward Incompatible)**
812

913
-

src/hyperframe/frame.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,11 @@ def _body_repr(self) -> str:
457457
return f"settings={self.settings}"
458458

459459
def serialize_body(self) -> bytes:
460-
return b"".join([_STRUCT_HL.pack(setting & 0xFFFF, value)
461-
for setting, value in self.settings.items()])
460+
return b"".join([_STRUCT_HL.pack(
461+
setting_identifier & 0xFFFF, # Settings identifiers are 16 bits, mask them appropriately, RFC 9113, Section 6.5.1
462+
setting_value & 0xFFFFFFFF, # Settings values are 32 bits, mask them appropriately, RFC 9113, Section 6.5.1
463+
)
464+
for setting_identifier, setting_value in self.settings.items()])
462465

463466
def parse_body(self, data: memoryview) -> None:
464467
if "ACK" in self.flags and len(data) > 0:

tests/test_frames.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,29 @@ def test_short_settings_frame_errors(self):
426426
with pytest.raises(InvalidDataError):
427427
decode_frame(self.serialized[:-2])
428428

429+
def test_settings_frame_with_large_setting_ids(self):
430+
f = SettingsFrame()
431+
f.settings[0xFFFE] = 12345
432+
f.settings[0xFFFF] = 54321
433+
434+
s = f.serialize()
435+
new_f = decode_frame(s)
436+
437+
assert new_f.settings[0xFFFE] == 12345
438+
assert new_f.settings[0xFFFF] == 54321
439+
440+
def test_settings_frame_serializes_with_large_setting_ids(self):
441+
f = SettingsFrame()
442+
f.settings[0xFFFE] = 12345
443+
f.settings[0xFFFF] = 54321
444+
445+
s = f.serialize()
446+
assert s == (
447+
b'\x00\x00\x0C\x04\x00\x00\x00\x00\x00' + # Frame header
448+
b'\xFF\xFE\x00\x00\x30\x39' + # Setting ID 0xFFFE
449+
b'\xFF\xFF\x00\x00\xd4\x31' # Setting ID 0xFFFF
450+
)
451+
429452

430453
class TestPushPromiseFrame:
431454
def test_repr(self):

0 commit comments

Comments
 (0)