Skip to content

Commit 15ea4a4

Browse files
[3.12] gh-111784: Fix two segfaults in the elementtree module (GH-113405) (GH-113446)
First fix resolve situation when pyexpat module (which contains expat_CAPI capsule) deallocates before _elementtree, so we need to hold a strong reference to pyexpat module to. Second fix resolve situation when module state is deallocated before deallocation of XMLParser instances, which uses module state to clear some stuff. (cherry picked from commit 894f0e5) Co-authored-by: Kirill Podoprigora <[email protected]>
1 parent 7f2ebc8 commit 15ea4a4

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix segfaults in the ``_elementtree`` module.
2+
Fix first segfault during deallocation of ``_elementtree.XMLParser`` instances by keeping strong reference
3+
to ``pyexpat`` module in module state for capsule lifetime.
4+
Fix second segfault which happens in the same deallocation process by keeping strong reference
5+
to ``_elementtree`` module in ``XMLParser`` structure for ``_elementtree`` module lifetime.

Modules/_elementtree.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ typedef struct {
9393
PyTypeObject *TreeBuilder_Type;
9494
PyTypeObject *XMLParser_Type;
9595

96+
PyObject *expat_capsule;
9697
struct PyExpat_CAPI *expat_capi;
9798
} elementtreestate;
9899

@@ -150,6 +151,7 @@ elementtree_clear(PyObject *m)
150151
Py_CLEAR(st->ElementIter_Type);
151152
Py_CLEAR(st->TreeBuilder_Type);
152153
Py_CLEAR(st->XMLParser_Type);
154+
Py_CLEAR(st->expat_capsule);
153155

154156
st->expat_capi = NULL;
155157
return 0;
@@ -170,6 +172,7 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg)
170172
Py_VISIT(st->ElementIter_Type);
171173
Py_VISIT(st->TreeBuilder_Type);
172174
Py_VISIT(st->XMLParser_Type);
175+
Py_VISIT(st->expat_capsule);
173176
return 0;
174177
}
175178

@@ -3065,6 +3068,7 @@ typedef struct {
30653068
PyObject *handle_close;
30663069

30673070
elementtreestate *state;
3071+
PyObject *elementtree_module;
30683072
} XMLParserObject;
30693073

30703074
/* helpers */
@@ -3611,7 +3615,11 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
36113615
self->handle_start = self->handle_data = self->handle_end = NULL;
36123616
self->handle_comment = self->handle_pi = self->handle_close = NULL;
36133617
self->handle_doctype = NULL;
3614-
self->state = get_elementtree_state_by_type(type);
3618+
self->elementtree_module = PyType_GetModuleByDef(type, &elementtreemodule);
3619+
assert(self->elementtree_module != NULL);
3620+
Py_INCREF(self->elementtree_module);
3621+
// See gh-111784 for explanation why is reference to module needed here.
3622+
self->state = get_elementtree_state(self->elementtree_module);
36153623
}
36163624
return (PyObject *)self;
36173625
}
@@ -3788,6 +3796,7 @@ xmlparser_gc_clear(XMLParserObject *self)
37883796
EXPAT(st, ParserFree)(parser);
37893797
}
37903798

3799+
Py_CLEAR(self->elementtree_module);
37913800
Py_CLEAR(self->handle_close);
37923801
Py_CLEAR(self->handle_pi);
37933802
Py_CLEAR(self->handle_comment);
@@ -4347,7 +4356,10 @@ module_exec(PyObject *m)
43474356
goto error;
43484357

43494358
/* link against pyexpat */
4350-
st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
4359+
if (!(st->expat_capsule = _PyImport_GetModuleAttrString("pyexpat", "expat_CAPI")))
4360+
goto error;
4361+
if (!(st->expat_capi = PyCapsule_GetPointer(st->expat_capsule, PyExpat_CAPSULE_NAME)))
4362+
goto error;
43514363
if (st->expat_capi) {
43524364
/* check that it's usable */
43534365
if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||

0 commit comments

Comments
 (0)