mirror of https://github.com/python/cpython
GH-103092: isolate `_elementtree` (#104561)
This commit is contained in:
parent
0afc473f50
commit
1b5a2b085c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue