Skip to content

Commit f0ee5cc

Browse files
Issue python#25455: Fixed a crash in repr of ElementTree.Element with recursive tag.
2 parents cf2ad55 + 9062c26 commit f0ee5cc

3 files changed

Lines changed: 25 additions & 4 deletions

File tree

Lib/test/test_xml_etree.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from itertools import product
2020
from test import support
21-
from test.support import TESTFN, findfile, import_fresh_module, gc_collect
21+
from test.support import TESTFN, findfile, import_fresh_module, gc_collect, swap_attr
2222

2323
# pyET is the pure-Python implementation.
2424
#
@@ -1864,6 +1864,12 @@ def __eq__(self, o):
18641864
e.extend([ET.Element('bar')])
18651865
self.assertRaises(ValueError, e.remove, X('baz'))
18661866

1867+
def test_recursive_repr(self):
1868+
# Issue #25455
1869+
e = ET.Element('foo')
1870+
with swap_attr(e, 'tag', e):
1871+
with self.assertRaises(RuntimeError):
1872+
repr(e) # Should not crash
18671873

18681874
class MutatingElementPath(str):
18691875
def __new__(cls, elem, *args):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Core and Builtins
4444
Library
4545
-------
4646

47+
- Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag.
48+
4749
- Issue #27294: Improved repr for Tkinter event objects.
4850

4951
- Issue #20508: Improve exception message of IPv{4,6}Network.__getitem__.

Modules/_elementtree.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,10 +1610,23 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
16101610
static PyObject*
16111611
element_repr(ElementObject* self)
16121612
{
1613-
if (self->tag)
1614-
return PyUnicode_FromFormat("<Element %R at %p>", self->tag, self);
1615-
else
1613+
int status;
1614+
1615+
if (self->tag == NULL)
16161616
return PyUnicode_FromFormat("<Element at %p>", self);
1617+
1618+
status = Py_ReprEnter((PyObject *)self);
1619+
if (status == 0) {
1620+
PyObject *res;
1621+
res = PyUnicode_FromFormat("<Element %R at %p>", self->tag, self);
1622+
Py_ReprLeave((PyObject *)self);
1623+
return res;
1624+
}
1625+
if (status > 0)
1626+
PyErr_Format(PyExc_RuntimeError,
1627+
"reentrant call inside %s.__repr__",
1628+
Py_TYPE(self)->tp_name);
1629+
return NULL;
16171630
}
16181631

16191632
/*[clinic input]

0 commit comments

Comments
 (0)