Skip to content

Commit feafd5f

Browse files
[3.13] gh-148735: Fix a UAF in Element.findtext() (GH-148738) (#148923)
(cherry picked from commit 0469e6d)
1 parent e4ae72a commit feafd5f

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

Lib/test/test_xml_etree.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,6 +3167,16 @@ def test_findtext_with_mutating(self):
31673167
e.extend([ET.Element('bar')])
31683168
e.findtext(cls(e, 'x'))
31693169

3170+
def test_findtext_with_mutating_non_none_text(self):
3171+
for cls in [MutationDeleteElementPath, MutationClearElementPath]:
3172+
with self.subTest(cls):
3173+
e = ET.Element('foo')
3174+
child = ET.Element('bar')
3175+
child.text = str(object())
3176+
e.append(child)
3177+
del child
3178+
repr(e.findtext(cls(e, 'x')))
3179+
31703180
def test_findtext_with_error(self):
31713181
e = ET.Element('foo')
31723182
e.extend([ET.Element('bar')])
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:mod:`xml.etree.ElementTree`: Fix a use-after-free in
2+
:meth:`Element.findtext <xml.etree.ElementTree.Element.findtext>` when the
3+
element tree is mutated concurrently during the search.

Modules/_elementtree.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ element_get_attrib(ElementObject* self)
563563
LOCAL(PyObject*)
564564
element_get_text(ElementObject* self)
565565
{
566-
/* return borrowed reference to text attribute */
566+
/* return new reference to text attribute */
567567

568568
PyObject *res = self->text;
569569

@@ -578,13 +578,13 @@ element_get_text(ElementObject* self)
578578
}
579579
}
580580

581-
return res;
581+
return Py_NewRef(res);
582582
}
583583

584584
LOCAL(PyObject*)
585585
element_get_tail(ElementObject* self)
586586
{
587-
/* return borrowed reference to text attribute */
587+
/* return new reference to tail attribute */
588588

589589
PyObject *res = self->tail;
590590

@@ -599,7 +599,7 @@ element_get_tail(ElementObject* self)
599599
}
600600
}
601601

602-
return res;
602+
return Py_NewRef(res);
603603
}
604604

605605
static PyObject*
@@ -1340,9 +1340,9 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls,
13401340
PyObject *text = element_get_text((ElementObject *)item);
13411341
Py_DECREF(item);
13421342
if (text == Py_None) {
1343+
Py_DECREF(text);
13431344
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
13441345
}
1345-
Py_XINCREF(text);
13461346
return text;
13471347
}
13481348
Py_DECREF(item);
@@ -2042,15 +2042,13 @@ element_tag_getter(ElementObject *self, void *closure)
20422042
static PyObject*
20432043
element_text_getter(ElementObject *self, void *closure)
20442044
{
2045-
PyObject *res = element_get_text(self);
2046-
return Py_XNewRef(res);
2045+
return element_get_text(self);
20472046
}
20482047

20492048
static PyObject*
20502049
element_tail_getter(ElementObject *self, void *closure)
20512050
{
2052-
PyObject *res = element_get_tail(self);
2053-
return Py_XNewRef(res);
2051+
return element_get_tail(self);
20542052
}
20552053

20562054
static PyObject*
@@ -2283,16 +2281,14 @@ elementiter_next(ElementIterObject *it)
22832281
continue;
22842282

22852283
gettext:
2284+
Py_DECREF(elem);
22862285
if (!text) {
2287-
Py_DECREF(elem);
22882286
return NULL;
22892287
}
22902288
if (text == Py_None) {
2291-
Py_DECREF(elem);
2289+
Py_DECREF(text);
22922290
}
22932291
else {
2294-
Py_INCREF(text);
2295-
Py_DECREF(elem);
22962292
rc = PyObject_IsTrue(text);
22972293
if (rc > 0)
22982294
return text;

0 commit comments

Comments
 (0)