Skip to content

Commit af6235f

Browse files
authored
PYTHON-5906 Raise ProtocolError for malformed OP_COMPRESSED messages in sync receive_message (#2937)
1 parent c8d65e1 commit af6235f

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

pymongo/network_layer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,10 @@ def receive_message(
775775
)
776776
data: memoryview | bytes
777777
if op_code == 2012:
778+
if length <= 25:
779+
raise ProtocolError(
780+
f"Message length ({length!r}) not longer than standard OP_COMPRESSED message header size (25)"
781+
)
778782
op_code, _, compressor_id = _UNPACK_COMPRESSION_HEADER(receive_data(conn, 9, deadline))
779783
data = decompress(receive_data(conn, length - 25, deadline), compressor_id)
780784
else:

test/test_network_layer.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ def test_length_exceeds_max_raises(self):
8080
with self.assertRaisesRegex(ProtocolError, "larger than server max"):
8181
network_layer.receive_message(conn, request_id=None)
8282

83+
def test_compressed_length_too_small_raises(self):
84+
# An OP_COMPRESSED frame with 16 < length <= 25 is malformed: it lacks
85+
# room for the 9-byte compression sub-header plus payload. It must raise
86+
# ProtocolError (not ValueError from a negative receive_data count).
87+
for length in (17, 24, 25):
88+
conn = _make_conn()
89+
_mock_recv_into(
90+
conn,
91+
pack_msg_header(length=length, request_id=0, response_to=0, op_code=2012),
92+
)
93+
with self.assertRaisesRegex(
94+
ProtocolError, "not longer than standard OP_COMPRESSED message header"
95+
):
96+
network_layer.receive_message(conn, request_id=None)
97+
8398
def test_unknown_opcode_raises(self):
8499
conn = _make_conn()
85100
_mock_recv_into(

0 commit comments

Comments
 (0)