GH-103092: isolate `_elementtree` (#104561)

This commit is contained in:
Kumar Aditya 2023-05-17 05:05:07 +05:30 committed by GitHub
parent 0afc473f50
commit 1b5a2b085c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 42 additions and 43 deletions

View File

@ -15,6 +15,8 @@
#include "Python.h"
#include "structmember.h" // PyMemberDef
#include "expat.h"
#include "pyexpat.h"
/* -------------------------------------------------------------------- */
/* configuration */
@ -90,6 +92,8 @@ typedef struct {
PyTypeObject *ElementIter_Type;
PyTypeObject *TreeBuilder_Type;
PyTypeObject *XMLParser_Type;
struct PyExpat_CAPI *expat_capi;
} elementtreestate;
static struct PyModuleDef elementtreemodule;
@ -146,6 +150,8 @@ elementtree_clear(PyObject *m)
Py_CLEAR(st->ElementIter_Type);
Py_CLEAR(st->TreeBuilder_Type);
Py_CLEAR(st->XMLParser_Type);
st->expat_capi = NULL;
return 0;
}
@ -3031,14 +3037,7 @@ _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag,
/* ==================================================================== */
/* the expat interface */
#include "expat.h"
#include "pyexpat.h"
/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be
* cached globally without being in per-module state.
*/
static struct PyExpat_CAPI *expat_capi;
#define EXPAT(func) (expat_capi->func)
#define EXPAT(st, func) ((st)->expat_capi->func)
static XML_Memory_Handling_Suite ExpatMemoryHandler = {
PyObject_Malloc, PyObject_Realloc, PyObject_Free};
@ -3147,7 +3146,7 @@ expat_set_error(elementtreestate *st, enum XML_Error error_code,
PyObject *errmsg, *error, *position, *code;
errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd",
message ? message : EXPAT(ErrorString)(error_code),
message ? message : EXPAT(st, ErrorString)(error_code),
line, column);
if (errmsg == NULL)
return;
@ -3227,8 +3226,8 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in,
expat_set_error(
st,
XML_ERROR_UNDEFINED_ENTITY,
EXPAT(GetErrorLineNumber)(self->parser),
EXPAT(GetErrorColumnNumber)(self->parser),
EXPAT(st, GetErrorLineNumber)(self->parser),
EXPAT(st, GetErrorColumnNumber)(self->parser),
message
);
}
@ -3648,8 +3647,8 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
Py_CLEAR(self->entity);
return -1;
}
self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
elementtreestate *st = self->state;
self->parser = EXPAT(st, ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}");
if (!self->parser) {
Py_CLEAR(self->entity);
Py_CLEAR(self->names);
@ -3657,15 +3656,14 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
return -1;
}
/* expat < 2.1.0 has no XML_SetHashSalt() */
if (EXPAT(SetHashSalt) != NULL) {
EXPAT(SetHashSalt)(self->parser,
if (EXPAT(st, SetHashSalt) != NULL) {
EXPAT(st, SetHashSalt)(self->parser,
(unsigned long)_Py_HashSecret.expat.hashsalt);
}
if (target != Py_None) {
Py_INCREF(target);
} else {
elementtreestate *st = self->state;
target = treebuilder_new(st->TreeBuilder_Type, NULL, NULL);
if (!target) {
Py_CLEAR(self->entity);
@ -3713,43 +3711,43 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
}
/* configure parser */
EXPAT(SetUserData)(self->parser, self);
EXPAT(st, SetUserData)(self->parser, self);
if (self->handle_start_ns || self->handle_end_ns)
EXPAT(SetNamespaceDeclHandler)(
EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
EXPAT(SetElementHandler)(
EXPAT(st, SetElementHandler)(
self->parser,
(XML_StartElementHandler) expat_start_handler,
(XML_EndElementHandler) expat_end_handler
);
EXPAT(SetDefaultHandlerExpand)(
EXPAT(st, SetDefaultHandlerExpand)(
self->parser,
(XML_DefaultHandler) expat_default_handler
);
EXPAT(SetCharacterDataHandler)(
EXPAT(st, SetCharacterDataHandler)(
self->parser,
(XML_CharacterDataHandler) expat_data_handler
);
if (self->handle_comment)
EXPAT(SetCommentHandler)(
EXPAT(st, SetCommentHandler)(
self->parser,
(XML_CommentHandler) expat_comment_handler
);
if (self->handle_pi)
EXPAT(SetProcessingInstructionHandler)(
EXPAT(st, SetProcessingInstructionHandler)(
self->parser,
(XML_ProcessingInstructionHandler) expat_pi_handler
);
EXPAT(SetStartDoctypeDeclHandler)(
EXPAT(st, SetStartDoctypeDeclHandler)(
self->parser,
(XML_StartDoctypeDeclHandler) expat_start_doctype_handler
);
EXPAT(SetUnknownEncodingHandler)(
EXPAT(st, SetUnknownEncodingHandler)(
self->parser,
EXPAT(DefaultUnknownEncodingHandler), NULL
EXPAT(st, DefaultUnknownEncodingHandler), NULL
);
return 0;
@ -3779,10 +3777,11 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
static int
xmlparser_gc_clear(XMLParserObject *self)
{
elementtreestate *st = self->state;
if (self->parser != NULL) {
XML_Parser parser = self->parser;
self->parser = NULL;
EXPAT(ParserFree)(parser);
EXPAT(st, ParserFree)(parser);
}
Py_CLEAR(self->handle_close);
@ -3830,7 +3829,7 @@ expat_parse(elementtreestate *st, XMLParserObject *self, const char *data,
int ok;
assert(!PyErr_Occurred());
ok = EXPAT(Parse)(self->parser, data, data_len, final);
ok = EXPAT(st, Parse)(self->parser, data, data_len, final);
if (PyErr_Occurred())
return NULL;
@ -3838,9 +3837,9 @@ expat_parse(elementtreestate *st, XMLParserObject *self, const char *data,
if (!ok) {
expat_set_error(
st,
EXPAT(GetErrorCode)(self->parser),
EXPAT(GetErrorLineNumber)(self->parser),
EXPAT(GetErrorColumnNumber)(self->parser),
EXPAT(st, GetErrorCode)(self->parser),
EXPAT(st, GetErrorLineNumber)(self->parser),
EXPAT(st, GetErrorColumnNumber)(self->parser),
NULL
);
return NULL;
@ -3911,7 +3910,7 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data)
return NULL;
}
/* Explicitly set UTF-8 encoding. Return code ignored. */
(void)EXPAT(SetEncoding)(self->parser, "utf-8");
(void)EXPAT(st, SetEncoding)(self->parser, "utf-8");
return expat_parse(st, self, data_ptr, (int)data_len, 0);
}
@ -4099,27 +4098,27 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self,
Py_XSETREF(target->end_event_obj, Py_NewRef(event_name_obj));
} else if (strcmp(event_name, "start-ns") == 0) {
Py_XSETREF(target->start_ns_event_obj, Py_NewRef(event_name_obj));
EXPAT(SetNamespaceDeclHandler)(
EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else if (strcmp(event_name, "end-ns") == 0) {
Py_XSETREF(target->end_ns_event_obj, Py_NewRef(event_name_obj));
EXPAT(SetNamespaceDeclHandler)(
EXPAT(st, SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else if (strcmp(event_name, "comment") == 0) {
Py_XSETREF(target->comment_event_obj, Py_NewRef(event_name_obj));
EXPAT(SetCommentHandler)(
EXPAT(st, SetCommentHandler)(
self->parser,
(XML_CommentHandler) expat_comment_handler
);
} else if (strcmp(event_name, "pi") == 0) {
Py_XSETREF(target->pi_event_obj, Py_NewRef(event_name_obj));
EXPAT(SetProcessingInstructionHandler)(
EXPAT(st, SetProcessingInstructionHandler)(
self->parser,
(XML_ProcessingInstructionHandler) expat_pi_handler
);
@ -4344,14 +4343,14 @@ module_exec(PyObject *m)
goto error;
/* link against pyexpat */
expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
if (expat_capi) {
st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0);
if (st->expat_capi) {
/* check that it's usable */
if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
(size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) ||
expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {
if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 ||
(size_t)st->expat_capi->size < sizeof(struct PyExpat_CAPI) ||
st->expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION ||
st->expat_capi->MINOR_VERSION != XML_MINOR_VERSION ||
st->expat_capi->MICRO_VERSION != XML_MICRO_VERSION) {
PyErr_SetString(PyExc_ImportError,
"pyexpat version is incompatible");
goto error;