Skip to content

Commit e34a5e3

Browse files
authored
gh-140593: Fix a memory leak in function my_ElementDeclHandler of pyexpat (#140602)
Ensure that the memory allocated for the content model passed to `my_ElementDeclHandler` is freed in all error paths.
1 parent 37827c1 commit e34a5e3

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

Lib/test/test_pyexpat.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,23 @@ def test_change_size_2(self):
684684
parser.Parse(xml2, True)
685685
self.assertEqual(self.n, 4)
686686

687+
class ElementDeclHandlerTest(unittest.TestCase):
688+
def test_trigger_leak(self):
689+
# Unfixed, this test would leak the memory of the so-called
690+
# "content model" in function ``my_ElementDeclHandler`` of pyexpat.
691+
# See https://github.com/python/cpython/issues/140593.
692+
data = textwrap.dedent('''\
693+
<!DOCTYPE quotations SYSTEM "quotations.dtd" [
694+
<!ELEMENT root ANY>
695+
]>
696+
<root/>
697+
''').encode('UTF-8')
698+
699+
parser = expat.ParserCreate()
700+
parser.NotStandaloneHandler = lambda: 1.234 # arbitrary float
701+
parser.ElementDeclHandler = lambda _1, _2: None
702+
self.assertRaises(TypeError, parser.Parse, data, True)
703+
687704
class MalformedInputTest(unittest.TestCase):
688705
def test1(self):
689706
xml = b"\0\r\n"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:mod:`xml.parsers.expat`: Fix a memory leak that could affect users with
2+
:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler` set to a custom
3+
element declaration handler. Patch by Sebastian Pipping.

Modules/pyexpat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ my_ElementDeclHandler(void *userData,
642642
PyObject *modelobj, *nameobj;
643643

644644
if (PyErr_Occurred())
645-
return;
645+
goto finally;
646646

647647
if (flush_character_buffer(self) < 0)
648648
goto finally;

0 commit comments

Comments
 (0)