Skip to content
14 changes: 14 additions & 0 deletions Lib/test/test_pyexpat.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,20 @@ def test_change_size_2(self):
parser.Parse(xml2, True)
self.assertEqual(self.n, 4)

@support.requires_resource('cpu')
@support.requires_resource('walltime')
def test_heap_overflow(self):
Comment thread
ByteFlowing1337 marked this conversation as resolved.
Outdated
# See https://github.com/python/cpython/issues/148441
parser = expat.ParserCreate()
parser.buffer_text = True
parser.buffer_size = 2**31 - 1 # INT_MAX
Comment thread
ByteFlowing1337 marked this conversation as resolved.
Outdated
def handler(text):
pass
N = 2049 * (1 << 20) - 3 # 2,148,532,221 bytes of character data
parser.CharacterDataHandler = handler
Comment thread
ByteFlowing1337 marked this conversation as resolved.
Outdated
xml_data = b"<r>" + b"A" * N + b"</r>"
self.assertEqual(parser.Parse(xml_data, True), 1)

class ElementDeclHandlerTest(unittest.TestCase):
def test_trigger_leak(self):
# Unfixed, this test would leak the memory of the so-called
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix heap buffer overflow in pyexpat CharacterDataHandler, which is caused by
two signed intergets added up.
Comment thread
ByteFlowing1337 marked this conversation as resolved.
Outdated
2 changes: 1 addition & 1 deletion Modules/pyexpat.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ my_CharacterDataHandler(void *userData, const XML_Char *data, int len)
if (self->buffer == NULL)
call_character_handler(self, data, len);
else {
if ((self->buffer_used + len) > self->buffer_size) {
if (len > (self->buffer_size - self->buffer_used)) {
if (flush_character_buffer(self) < 0)
return;
/* handler might have changed; drop the rest on the floor
Expand Down
Loading