From 041ca2de2db067f0155200471f283ae92a35b744 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 12 Nov 2026 18:30:04 -0300 Subject: [PATCH] gh-158032: Keep the element tag alive during Element.iter comparison (GH-158044) (cherry picked from commit 78a70f862e3b7f28c62bd9352af83920678f399a) Co-authored-by: Lucas --- Lib/test/test_xml_etree_c.py | 29 +++++++++++++++++++ ...-09-23-21-15-00.gh-issue-158032.k4nT9p.rst | 2 ++ Modules/_elementtree.c | 4 ++- 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-09-23-21-15-00.gh-issue-158032.k4nT9p.rst diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index 7f9cecbc450381b..fec7b8a8dd03dbc 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -161,6 +161,35 @@ def test_xmlpullparser_leaks(self): del parser support.gc_collect() + def test_iter_tag_reentrant_compare(self): + destroyed = [] + compared = [] + + class Tag: + def __del__(self): + destroyed.append(True) + + def __eq__(self, other): + child.tag = "replaced" + return NotImplemented + + __hash__ = object.__hash__ + + class Sought: + def __eq__(self, other): + if isinstance(other, Tag): + compared.append(not destroyed) + return NotImplemented + + __hash__ = object.__hash__ + + root = cET.Element("root") + child = cET.SubElement(root, "x") + child.tag = Tag() + self.assertEqual(list(root.iter(Sought())), []) + self.assertEqual(compared, [True]) + self.assertEqual(child.tag, "replaced") + def test_dict_disappearing_during_get_item(self): # test fix for seg fault reported in issue 27946 class X: diff --git a/Misc/NEWS.d/next/Library/2026-09-23-21-15-00.gh-issue-158032.k4nT9p.rst b/Misc/NEWS.d/next/Library/2026-09-23-21-15-00.gh-issue-158032.k4nT9p.rst new file mode 100644 index 000000000000000..0e0a565519fa8e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-23-21-15-00.gh-issue-158032.k4nT9p.rst @@ -0,0 +1,2 @@ +Fix a crash in :meth:`xml.etree.ElementTree.Element.iter` when a tag's +equality comparison replaces that tag. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 63cbbaf45d39544..dd25f5d56aee518 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2300,7 +2300,9 @@ elementiter_next(PyObject *op) if (it->sought_tag == Py_None) return (PyObject *)elem; - rc = PyObject_RichCompareBool(elem->tag, it->sought_tag, Py_EQ); + PyObject *tag = Py_NewRef(elem->tag); + rc = PyObject_RichCompareBool(tag, it->sought_tag, Py_EQ); + Py_DECREF(tag); if (rc > 0) return (PyObject *)elem;