Skip to content

Commit 8d2d68f

Browse files
committed
gh-146056: Fix TreeBuilder stack in xml.etree
No longer create a stack of 20 items, but create an empty stack instead. It prevents crashes when the stack list is discovered by gc.get_referrers() or other functions. Fix also reference counting in treebuilder_handle_end().
1 parent 99e2c5e commit 8d2d68f

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

Lib/test/test_xml_etree_c.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# xml.etree test for cElementTree
2+
import gc
23
import io
34
import struct
45
from test import support
@@ -203,6 +204,23 @@ def test_disallow_instantiation(self):
203204
iter_type = type(root.iter())
204205
support.check_disallow_instantiation(self, iter_type)
205206

207+
def test_tree_builder_stack(self):
208+
builder = cET.TreeBuilder()
209+
for x in range(10):
210+
builder.start("a", {})
211+
for x in range(10):
212+
builder.end("a")
213+
root = builder.close()
214+
215+
# Find the internal TreeBuilder stack list using gc.get_referrers()
216+
for ref in gc.get_referrers(root[0]):
217+
if isinstance(ref, list):
218+
# Check that the list doesn't contain NULL items (gh-146056)
219+
repr(ref)
220+
break
221+
else:
222+
self.fail("failed to find TreeBuilder stack list")
223+
206224

207225
@unittest.skipUnless(cET, 'requires _elementtree')
208226
class TestAliasWorking(unittest.TestCase):

Modules/_elementtree.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,7 +2431,7 @@ treebuilder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
24312431
t->element_factory = NULL;
24322432
t->comment_factory = NULL;
24332433
t->pi_factory = NULL;
2434-
t->stack = PyList_New(20);
2434+
t->stack = PyList_New(0);
24352435
if (!t->stack) {
24362436
Py_DECREF(t->this);
24372437
Py_DECREF(t->last);
@@ -2856,9 +2856,9 @@ treebuilder_handle_end(TreeBuilderObject* self, PyObject* tag)
28562856

28572857
item = self->last;
28582858
self->last = Py_NewRef(self->this);
2859-
Py_XSETREF(self->last_for_tail, self->last);
2859+
Py_XSETREF(self->last_for_tail, Py_NewRef(self->last));
28602860
self->index--;
2861-
self->this = Py_NewRef(PyList_GET_ITEM(self->stack, self->index));
2861+
Py_SETREF(self->this, Py_NewRef(PyList_GET_ITEM(self->stack, self->index)));
28622862
Py_DECREF(item);
28632863

28642864
if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0)

0 commit comments

Comments
 (0)