From 4670d5edbf04c8a963d5e1857b941722f21e2afd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 14 Dec 2018 23:56:54 +0200 Subject: [PATCH 1/2] bpo-35502: Fix reference leaks in ElementTree.TreeBuilder. --- Lib/test/test_xml_etree_c.py | 17 +++++++++++++++++ .../2018-12-14-23-56-48.bpo-35502.gLHuFS.rst | 2 ++ Modules/_elementtree.c | 5 +++++ 3 files changed, 24 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index e87de6094441e13..c2b6e938a8322f4 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -1,4 +1,5 @@ # xml.etree test for cElementTree +import io import struct from test import support from test.support import import_fresh_module @@ -133,6 +134,22 @@ def test_setstate_leaks(self): self.assertEqual(len(elem), 1) self.assertEqual(elem[0].tag, 'child') + def test_iterparse_leaks(self): + # Test reference leaks in TreeBuilder (issue #35502). + XML = '' + parser = cET.iterparse(io.StringIO(XML)) + next(parser) + del parser + support.gc_collect() + + def test_xmlpullparser_leaks(self): + # Test reference leaks in TreeBuilder (issue #35502). + XML = '' + parser = cET.XMLPullParser() + parser.feed(XML) + del parser + support.gc_collect() + @unittest.skipUnless(cET, 'requires _elementtree') class TestAliasWorking(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst b/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst new file mode 100644 index 000000000000000..300094e72b781cf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst @@ -0,0 +1,2 @@ +Fixed reference leaks in :class:`xml.etree.ElementTree.TreeBuilder` in case +of unfinished building of the tree. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 12e418d85ed5d6d..b1a96299f24fe19 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2447,6 +2447,11 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self, static int treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg) { + Py_VISIT(self->end_ns_event_obj); + Py_VISIT(self->start_ns_event_obj); + Py_VISIT(self->end_event_obj); + Py_VISIT(self->start_event_obj); + Py_VISIT(self->events_append); Py_VISIT(self->root); Py_VISIT(self->this); Py_VISIT(self->last); From 8383fa706bc16874536ca01c080ee226838120d6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 18 Dec 2018 13:46:55 +0200 Subject: [PATCH 2/2] Address review comments. --- Lib/test/test_xml_etree_c.py | 4 ++++ .../next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index c2b6e938a8322f4..2144d203e1e95ce 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -136,6 +136,8 @@ def test_setstate_leaks(self): def test_iterparse_leaks(self): # Test reference leaks in TreeBuilder (issue #35502). + # The test is written to be executed in the hunting reference leaks + # mode. XML = '' parser = cET.iterparse(io.StringIO(XML)) next(parser) @@ -144,6 +146,8 @@ def test_iterparse_leaks(self): def test_xmlpullparser_leaks(self): # Test reference leaks in TreeBuilder (issue #35502). + # The test is written to be executed in the hunting reference leaks + # mode. XML = '' parser = cET.XMLPullParser() parser.feed(XML) diff --git a/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst b/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst index 300094e72b781cf..0fcea8d5a41df1f 100644 --- a/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst +++ b/Misc/NEWS.d/next/Library/2018-12-14-23-56-48.bpo-35502.gLHuFS.rst @@ -1,2 +1,3 @@ Fixed reference leaks in :class:`xml.etree.ElementTree.TreeBuilder` in case -of unfinished building of the tree. +of unfinished building of the tree (in particular when an error was raised +during parsing XML).