From 9062c261a4f9268f4621548ec205c80411f75b6e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2016 09:43:55 +0300 Subject: [PATCH] Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag. --- Lib/test/test_xml_etree.py | 8 +++++++- Misc/NEWS | 2 ++ Modules/_elementtree.c | 19 ++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 44e3142dc91..bc1dd1461be 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -18,7 +18,7 @@ import weakref from itertools import product from test import support -from test.support import TESTFN, findfile, import_fresh_module, gc_collect +from test.support import TESTFN, findfile, import_fresh_module, gc_collect, swap_attr # pyET is the pure-Python implementation. # @@ -1860,6 +1860,12 @@ class BadElementTest(ElementTestCase, unittest.TestCase): e.extend([ET.Element('bar')]) self.assertRaises(ValueError, e.remove, X('baz')) + def test_recursive_repr(self): + # Issue #25455 + e = ET.Element('foo') + with swap_attr(e, 'tag', e): + with self.assertRaises(RuntimeError): + repr(e) # Should not crash class MutatingElementPath(str): def __new__(cls, elem, *args): diff --git a/Misc/NEWS b/Misc/NEWS index 9d826265387..19cb832f4b2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,8 @@ Core and Builtins Library ------- +- Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag. + - Issue #26556: Update expat to 2.1.1, fixes CVE-2015-1283. - Fix TLS stripping vulnerability in smptlib, CVE-2016-0772. Reported by Team diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 0f1d6a1faa4..85ffca206ba 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1582,10 +1582,23 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) static PyObject* element_repr(ElementObject* self) { - if (self->tag) - return PyUnicode_FromFormat("", self->tag, self); - else + int status; + + if (self->tag == NULL) return PyUnicode_FromFormat("", self); + + status = Py_ReprEnter((PyObject *)self); + if (status == 0) { + PyObject *res; + res = PyUnicode_FromFormat("", self->tag, self); + Py_ReprLeave((PyObject *)self); + return res; + } + if (status > 0) + PyErr_Format(PyExc_RuntimeError, + "reentrant call inside %s.__repr__", + Py_TYPE(self)->tp_name); + return NULL; } /*[clinic input]