Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Lib/test/test_xml_etree_c.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# xml.etree test for cElementTree
import io
import struct
from test import support
from test.support import import_fresh_module
Expand Down Expand Up @@ -133,6 +134,26 @@ 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).
Comment thread
vstinner marked this conversation as resolved.
# The test is written to be executed in the hunting reference leaks
# mode.
XML = '<a></a></b>'
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).
# The test is written to be executed in the hunting reference leaks
# mode.
XML = '<a></a></b>'
parser = cET.XMLPullParser()
parser.feed(XML)
del parser
support.gc_collect()


@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fixed reference leaks in :class:`xml.etree.ElementTree.TreeBuilder` in case
of unfinished building of the tree (in particular when an error was raised
during parsing XML).
5 changes: 5 additions & 0 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down