Skip to content

Commit

Permalink
GH-103092: isolate _elementtree (#104561)
Browse files Browse the repository at this point in the history
  • Loading branch information
kumaraditya303 authored May 16, 2023
1 parent 0afc473 commit 1b5a2b0
Showing 1 changed file with 42 additions and 43 deletions.
85 changes: 42 additions & 43 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include "Python.h"
#include "structmember.h" // PyMemberDef
#include "expat.h"
#include "pyexpat.h"

/* -------------------------------------------------------------------- */
/* configuration */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
);
}
Expand Down Expand Up @@ -3648,24 +3647,23 @@ _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);
PyErr_NoMemory();
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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -3830,17 +3829,17 @@ 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;

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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1b5a2b0

Please sign in to comment.