]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-148735: Fix a UAF in `Element.findtext()` (GH-148738) (#148916)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 24 Apr 2026 20:38:15 +0000 (22:38 +0200)
committerGitHub <noreply@github.com>
Fri, 24 Apr 2026 20:38:15 +0000 (21:38 +0100)
(cherry picked from commit 0469e6d38dcb3ff904690028cb3a25155bdcedae)

Co-authored-by: Stan Ulbrych <stan@python.org>
Lib/test/test_xml_etree.py
Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst [new file with mode: 0644]
Modules/_elementtree.c

index b207dbe68be94cf486e54e9e34bf395befd3447b..2f66c6b80d1436dedb780e08e6b9f97db3612d68 100644 (file)
@@ -3179,6 +3179,16 @@ class BadElementPathTest(ElementTestCase, unittest.TestCase):
                 e.extend([ET.Element('bar')])
                 e.findtext(cls(e, 'x'))
 
+    def test_findtext_with_mutating_non_none_text(self):
+        for cls in [MutationDeleteElementPath, MutationClearElementPath]:
+            with self.subTest(cls):
+                e = ET.Element('foo')
+                child = ET.Element('bar')
+                child.text = str(object())
+                e.append(child)
+                del child
+                repr(e.findtext(cls(e, 'x')))
+
     def test_findtext_with_error(self):
         e = ET.Element('foo')
         e.extend([ET.Element('bar')])
diff --git a/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst b/Misc/NEWS.d/next/Library/2026-04-18-21-39-15.gh-issue-148735.siw6DG.rst
new file mode 100644 (file)
index 0000000..db5e94c
--- /dev/null
@@ -0,0 +1,3 @@
+:mod:`xml.etree.ElementTree`: Fix a use-after-free in
+:meth:`Element.findtext <xml.etree.ElementTree.Element.findtext>` when the
+element tree is mutated concurrently during the search.
index 496864175725e635b40aa994b9e27c0650db63af..7ca03f1561b51b14eb7c5cf034507eb17976084f 100644 (file)
@@ -564,7 +564,7 @@ element_get_attrib(ElementObject* self)
 LOCAL(PyObject*)
 element_get_text(ElementObject* self)
 {
-    /* return borrowed reference to text attribute */
+    /* return new reference to text attribute */
 
     PyObject *res = self->text;
 
@@ -579,13 +579,13 @@ element_get_text(ElementObject* self)
         }
     }
 
-    return res;
+    return Py_NewRef(res);
 }
 
 LOCAL(PyObject*)
 element_get_tail(ElementObject* self)
 {
-    /* return borrowed reference to text attribute */
+    /* return new reference to tail attribute */
 
     PyObject *res = self->tail;
 
@@ -600,7 +600,7 @@ element_get_tail(ElementObject* self)
         }
     }
 
-    return res;
+    return Py_NewRef(res);
 }
 
 static PyObject*
@@ -1350,9 +1350,9 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls,
             PyObject *text = element_get_text((ElementObject *)item);
             Py_DECREF(item);
             if (text == Py_None) {
+                Py_DECREF(text);
                 return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
             }
-            Py_XINCREF(text);
             return text;
         }
         Py_DECREF(item);
@@ -2056,16 +2056,14 @@ static PyObject*
 element_text_getter(PyObject *op, void *closure)
 {
     ElementObject *self = _Element_CAST(op);
-    PyObject *res = element_get_text(self);
-    return Py_XNewRef(res);
+    return element_get_text(self);
 }
 
 static PyObject*
 element_tail_getter(PyObject *op, void *closure)
 {
     ElementObject *self = _Element_CAST(op);
-    PyObject *res = element_get_tail(self);
-    return Py_XNewRef(res);
+    return element_get_tail(self);
 }
 
 static PyObject*
@@ -2308,16 +2306,14 @@ elementiter_next(PyObject *op)
         continue;
 
 gettext:
+        Py_DECREF(elem);
         if (!text) {
-            Py_DECREF(elem);
             return NULL;
         }
         if (text == Py_None) {
-            Py_DECREF(elem);
+            Py_DECREF(text);
         }
         else {
-            Py_INCREF(text);
-            Py_DECREF(elem);
             rc = PyObject_IsTrue(text);
             if (rc > 0)
                 return text;