Skip to content

Commit 05b1663

Browse files
StanFromIrelandmiss-islington
authored andcommitted
gh-148735: Fix a UAF in Element.findtext() (GH-148738)
(cherry picked from commit 0469e6d) Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 0f656e2 commit 05b1663

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
@@ -3179,6 +3179,16 @@ def test_findtext_with_mutating(self):
31793179
e.extend([ET.Element('bar')])
31803180
e.findtext(cls(e, 'x'))
31813181

3182+
def test_findtext_with_mutating_non_none_text(self):
3183+
for cls in [MutationDeleteElementPath, MutationClearElementPath]:
3184+
with self.subTest(cls):
3185+
e = ET.Element('foo')
3186+
child = ET.Element('bar')
3187+
child.text = str(object())
3188+
e.append(child)
3189+
del child
3190+
repr(e.findtext(cls(e, 'x')))
3191+
31823192
def test_findtext_with_error(self):
31833193
e = ET.Element('foo')
31843194
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
@@ -564,7 +564,7 @@ element_get_attrib(ElementObject* self)
564564
LOCAL(PyObject*)
565565
element_get_text(ElementObject* self)
566566
{
567-
/* return borrowed reference to text attribute */
567+
/* return new reference to text attribute */
568568

569569
PyObject *res = self->text;
570570

@@ -579,13 +579,13 @@ element_get_text(ElementObject* self)
579579
}
580580
}
581581

582-
return res;
582+
return Py_NewRef(res);
583583
}
584584

585585
LOCAL(PyObject*)
586586
element_get_tail(ElementObject* self)
587587
{
588-
/* return borrowed reference to text attribute */
588+
/* return new reference to tail attribute */
589589

590590
PyObject *res = self->tail;
591591

@@ -600,7 +600,7 @@ element_get_tail(ElementObject* self)
600600
}
601601
}
602602

603-
return res;
603+
return Py_NewRef(res);
604604
}
605605

606606
static PyObject*
@@ -1350,9 +1350,9 @@ _elementtree_Element_findtext_impl(ElementObject *self, PyTypeObject *cls,
13501350
PyObject *text = element_get_text((ElementObject *)item);
13511351
Py_DECREF(item);
13521352
if (text == Py_None) {
1353+
Py_DECREF(text);
13531354
return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
13541355
}
1355-
Py_XINCREF(text);
13561356
return text;
13571357
}
13581358
Py_DECREF(item);
@@ -2056,16 +2056,14 @@ static PyObject*
20562056
element_text_getter(PyObject *op, void *closure)
20572057
{
20582058
ElementObject *self = _Element_CAST(op);
2059-
PyObject *res = element_get_text(self);
2060-
return Py_XNewRef(res);
2059+
return element_get_text(self);
20612060
}
20622061

20632062
static PyObject*
20642063
element_tail_getter(PyObject *op, void *closure)
20652064
{
20662065
ElementObject *self = _Element_CAST(op);
2067-
PyObject *res = element_get_tail(self);
2068-
return Py_XNewRef(res);
2066+
return element_get_tail(self);
20692067
}
20702068

20712069
static PyObject*
@@ -2308,16 +2306,14 @@ elementiter_next(PyObject *op)
23082306
continue;
23092307

23102308
gettext:
2309+
Py_DECREF(elem);
23112310
if (!text) {
2312-
Py_DECREF(elem);
23132311
return NULL;
23142312
}
23152313
if (text == Py_None) {
2316-
Py_DECREF(elem);
2314+
Py_DECREF(text);
23172315
}
23182316
else {
2319-
Py_INCREF(text);
2320-
Py_DECREF(elem);
23212317
rc = PyObject_IsTrue(text);
23222318
if (rc > 0)
23232319
return text;

0 commit comments

Comments
 (0)