summaryrefslogtreecommitdiffstats
path: root/Modules/_elementtree.c
diff options
context:
space:
mode:
authorKirill Podoprigora <kirill.bast9@mail.ru>2023-12-24 08:57:41 (GMT)
committerGitHub <noreply@github.com>2023-12-24 08:57:41 (GMT)
commit894f0e573d9eb49cd5864c44328f10a731852dab (patch)
tree76ff0bee26f5bfff45e78f56d61f7a3a7e755acb /Modules/_elementtree.c
parent050783cb37d6a09d8238fa640814df8a915f6a68 (diff)
downloadcpython-894f0e573d9eb49cd5864c44328f10a731852dab.zip
cpython-894f0e573d9eb49cd5864c44328f10a731852dab.tar.gz
cpython-894f0e573d9eb49cd5864c44328f10a731852dab.tar.bz2
gh-111784: Fix two segfaults in the elementtree module (GH-113405)
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.
Diffstat (limited to 'Modules/_elementtree.c')
-rw-r--r--Modules/_elementtree.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index f9d5793..5bf6787 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -98,6 +98,7 @@ typedef struct {
PyTypeObject *TreeBuilder_Type;
PyTypeObject *XMLParser_Type;
+ PyObject *expat_capsule;
struct PyExpat_CAPI *expat_capi;
} elementtreestate;
@@ -155,6 +156,7 @@ elementtree_clear(PyObject *m)
Py_CLEAR(st->ElementIter_Type);
Py_CLEAR(st->TreeBuilder_Type);
Py_CLEAR(st->XMLParser_Type);
+ Py_CLEAR(st->expat_capsule);
st->expat_capi = NULL;
return 0;
@@ -175,6 +177,7 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg)
Py_VISIT(st->ElementIter_Type);
Py_VISIT(st->TreeBuilder_Type);
Py_VISIT(st->XMLParser_Type);
+ Py_VISIT(st->expat_capsule);
return 0;
}
@@ -3066,6 +3069,7 @@ typedef struct {
PyObject *handle_close;
elementtreestate *state;
+ PyObject *elementtree_module;
} XMLParserObject;
/* helpers */
@@ -3607,7 +3611,11 @@ xmlparser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->handle_start = self->handle_data = self->handle_end = NULL;
self->handle_comment = self->handle_pi = self->handle_close = NULL;
self->handle_doctype = NULL;
- self->state = get_elementtree_state_by_type(type);
+ self->elementtree_module = PyType_GetModuleByDef(type, &elementtreemodule);
+ assert(self->elementtree_module != NULL);
+ Py_INCREF(self->elementtree_module);
+ // See gh-111784 for explanation why is reference to module needed here.
+ self->state = get_elementtree_state(self->elementtree_module);
}
return (PyObject *)self;
}
@@ -3784,6 +3792,7 @@ xmlparser_gc_clear(XMLParserObject *self)
EXPAT(st, ParserFree)(parser);
}
+ Py_CLEAR(self->elementtree_module);
Py_CLEAR(self->handle_close);
Py_CLEAR(self->handle_pi);
Py_CLEAR(self->handle_comment);
@@ -4343,7 +4352,10 @@ module_exec(PyObject *m)
goto error;
/* link against pyexpat */
- st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
+ if (!(st->expat_capsule = _PyImport_GetModuleAttrString("pyexpat", "expat_CAPI")))
+ goto error;
+ if (!(st->expat_capi = PyCapsule_GetPointer(st->expat_capsule, PyExpat_CAPSULE_NAME)))
+ goto error;
if (st->expat_capi) {
/* check that it's usable */
if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||