@@ -1758,6 +1758,45 @@ def test_array_of_documents_to_buffer(self):
17581758 with self .assertRaises (InvalidBSON ):
17591759 _array_of_documents_to_buffer (buf )
17601760
1761+ def test_array_of_documents_to_buffer_rejects_oversized_element (self ):
1762+ # Regression test for the bound check in
1763+ # _cbson_array_of_documents_to_buffer: an embedded document whose
1764+ # declared length exceeds the bytes remaining in the array document
1765+ # must raise InvalidBSON before any copy, rather than reading out of
1766+ # bounds (CWE-125).
1767+ doc = dict (a = 1 )
1768+ valid = encode ({"0" : doc })
1769+ # A well-formed buffer is unaffected by the guard.
1770+ self .assertEqual (_array_of_documents_to_buffer (valid ), encode (doc ))
1771+ # The first embedded document starts after the array header:
1772+ # 4-byte array length + 1-byte element type (0x03) + "0\x00" key = 7.
1773+ # Its leading 4 bytes are the embedded document's declared length.
1774+ offset = 4 + 1 + 2
1775+ malformed = bytearray (valid )
1776+ # Claim a length far larger than what remains (but >= BSON_MIN_SIZE so
1777+ # the existing lower-bound check still passes), forcing the new
1778+ # upper-bound guard to reject it.
1779+ malformed [offset : offset + 4 ] = struct .pack ("<i" , 0x7FFF )
1780+ # The C fast-path raises a dedicated "invalid array content" error from the
1781+ # new bound check; the pure-Python path reaches the same invariant through
1782+ # _get_object_size, which raises "invalid object length".
1783+ expected = "invalid array content" if bson .has_c () else "invalid object length"
1784+ with self .assertRaisesRegex (InvalidBSON , expected ):
1785+ _array_of_documents_to_buffer (bytes (malformed ))
1786+
1787+ def test_array_of_documents_to_buffer_rejects_element_consuming_terminator (self ):
1788+ doc = dict (a = 1 )
1789+ valid = encode ({"0" : doc })
1790+ self .assertEqual (_array_of_documents_to_buffer (valid ), encode (doc ))
1791+ offset = 4 + 1 + 2
1792+ malformed = bytearray (valid )
1793+ value_length = len (valid ) - offset
1794+ malformed [offset : offset + 4 ] = struct .pack ("<i" , value_length )
1795+ # Covers the exact boundary where the embedded doc consumes the array's EOO byte.
1796+ expected = "invalid array content" if bson .has_c () else "invalid object length"
1797+ with self .assertRaisesRegex (InvalidBSON , expected ):
1798+ _array_of_documents_to_buffer (bytes (malformed ))
1799+
17611800 def test_datetime_ms_hash (self ):
17621801 # Equal values must have equal hashes.
17631802 self .assertEqual (hash (DatetimeMS (0 )), hash (DatetimeMS (0 )))
0 commit comments