Skip to content

Commit 502534e

Browse files
miss-islingtonByteFlowing1337picnixzserhiy-storchakavstinner
authored
[3.13] gh-148441: Avoid integer overflow in Expat's CharacterDataHandler (GH-148904) (#149637)
* gh-148441: Avoid integer overflow in Expat's CharacterDataHandler (GH-148904) (cherry picked from commit bc1be4f) Co-authored-by: ByteFlow <fakeshadow1337@gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> * Apply suggestion from @picnixz Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --------- Co-authored-by: ByteFlow <fakeshadow1337@gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent ffa440a commit 502534e

3 files changed

Lines changed: 19 additions & 1 deletion

File tree

Lib/test/test_pyexpat.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,20 @@ def test_change_size_2(self):
783783
parser.Parse(xml2, True)
784784
self.assertEqual(self.n, 4)
785785

786+
@support.requires_resource('cpu')
787+
@support.requires_resource('walltime')
788+
@support.bigmemtest(size=2**31, memuse=4, dry_run=False)
789+
def test_large_character_data_does_not_crash(self, size):
790+
# See https://github.com/python/cpython/issues/148441
791+
parser = expat.ParserCreate()
792+
parser.buffer_text = True
793+
parser.buffer_size = 2**31 - 1 # INT_MAX
794+
N = 2049 * (1 << 20) - 3 # Character data greater than INT_MAX
795+
self.assertGreater(N, parser.buffer_size)
796+
parser.CharacterDataHandler = lambda text: None
797+
xml_data = b"<r>" + b"A" * N + b"</r>"
798+
self.assertEqual(parser.Parse(xml_data, True), 1)
799+
786800
class ElementDeclHandlerTest(unittest.TestCase):
787801
def test_trigger_leak(self):
788802
# Unfixed, this test would leak the memory of the so-called
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:mod:`xml.parsers.expat`: prevent a crash in
2+
:meth:`~xml.parsers.expat.xmlparser.CharacterDataHandler`
3+
when the character data size exceeds the parser's
4+
:attr:`buffer size <xml.parsers.expat.xmlparser.buffer_size>`.

Modules/pyexpat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ my_CharacterDataHandler(void *userData, const XML_Char *data, int len)
371371
if (self->buffer == NULL)
372372
call_character_handler(self, data, len);
373373
else {
374-
if ((self->buffer_used + len) > self->buffer_size) {
374+
if (len > (self->buffer_size - self->buffer_used)) {
375375
if (flush_character_buffer(self) < 0)
376376
return;
377377
/* handler might have changed; drop the rest on the floor

0 commit comments

Comments
 (0)