Skip to content

Commit b31117c

Browse files
authored
Merge branch 'master' into fix-reserved-bit-parsing
2 parents daed28c + 33b7d06 commit b31117c

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ dev
99
- GoAwayFrame and WindowUpdateFrame now correctly mask off the reserved bit during
1010
parsing and serialization of stream IDs and window increments, as per RFC 9113,
1111
Sections 6.8 and 6.9.
12+
- Setting Identifier are now correctly serialized as 16-bit values, instead of 8-bit.
1213

1314
**API Changes (Backward Incompatible)**
1415

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 & 0xFF, 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)