[Python-checkins] cpython (2.7): Issue #28871: Fixed a crash when deallocate deep ElementTree.

serhiy.storchaka python-checkins at python.org
Wed Dec 21 05:56:42 EST 2016


https://hg.python.org/cpython/rev/78bf34b6a713
changeset:   105767:78bf34b6a713
branch:      2.7
parent:      105762:32cc37a89b58
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Wed Dec 21 12:55:28 2016 +0200
summary:
  Issue #28871: Fixed a crash when deallocate deep ElementTree.
Fixed running MiscTests in test_xml_etree_c.

files:
  Lib/test/test_xml_etree_c.py |  11 ++++++++++
  Misc/NEWS                    |   2 +
  Modules/_elementtree.c       |  25 +++++++++++++++++++----
  3 files changed, 33 insertions(+), 5 deletions(-)


diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py
--- a/Lib/test/test_xml_etree_c.py
+++ b/Lib/test/test_xml_etree_c.py
@@ -17,6 +17,7 @@
     """
 
 
+ at unittest.skipUnless(cET, 'requires _elementtree')
 class MiscTests(unittest.TestCase):
     # Issue #8651.
     @precisionbigmemtest(size=_2G + 100, memuse=1)
@@ -62,12 +63,22 @@
             del element.attrib
         self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
 
+    def test_trashcan(self):
+        # If this test fails, it will most likely die via segfault.
+        e = root = cET.Element('root')
+        for i in range(200000):
+            e = cET.SubElement(e, 'x')
+        del e
+        del root
+        test_support.gc_collect()
+
 
 def test_main():
     from test import test_xml_etree, test_xml_etree_c
 
     # Run the tests specific to the C implementation
     test_support.run_doctest(test_xml_etree_c, verbosity=True)
+    test_support.run_unittest(MiscTests)
 
     # Assign the C implementation before running the doctests
     # Patch the __name__, to prevent confusion with the pure Python test
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,8 @@
 - Issue #29019: Fix dict.fromkeys(x) overallocates when x is sparce dict.
   Original patch by Rasmus Villemoes.
 
+- Issue #28871: Fixed a crash when deallocate deep ElementTree.
+
 - Issue #19542: Fix bugs in WeakValueDictionary.setdefault() and
   WeakValueDictionary.pop() when a GC collection happens in another
   thread.
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -121,6 +121,18 @@
 #define JOIN_SET(p, flag) ((void*) ((Py_uintptr_t) (JOIN_OBJ(p)) | (flag)))
 #define JOIN_OBJ(p) ((PyObject*) ((Py_uintptr_t) (p) & ~1))
 
+/* Py_CLEAR for a PyObject* that uses a join flag. Pass the pointer by
+ * reference since this function sets it to NULL.
+*/
+static void _clear_joined_ptr(PyObject **p)
+{
+    if (*p) {
+        PyObject *tmp = JOIN_OBJ(*p);
+        *p = NULL;
+        Py_DECREF(tmp);
+    }
+}
+
 /* glue functions (see the init function for details) */
 static PyObject* elementtree_parseerror_obj;
 static PyObject* elementtree_copyelement_obj;
@@ -538,17 +550,20 @@
 static void
 element_dealloc(ElementObject* self)
 {
+    Py_TRASHCAN_SAFE_BEGIN(self)
+
+    /* discard attributes */
+    Py_DECREF(self->tag);
+    _clear_joined_ptr(&self->text);
+    _clear_joined_ptr(&self->tail);
+
     if (self->extra)
         element_dealloc_extra(self);
 
-    /* discard attributes */
-    Py_DECREF(self->tag);
-    Py_DECREF(JOIN_OBJ(self->text));
-    Py_DECREF(JOIN_OBJ(self->tail));
-
     RELEASE(sizeof(ElementObject), "destroy element");
 
     PyObject_Del(self);
+    Py_TRASHCAN_SAFE_END(self)
 }
 
 /* -------------------------------------------------------------------- */

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list