gh-111178: fix UBSan failures in `_elementtree.c` (#127982)

This commit is contained in:
Bénédikt Tran 2024-12-16 14:40:26 +01:00 committed by GitHub
parent 47c5a0f307
commit 0d8e7106c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 80 additions and 53 deletions

View File

@ -184,7 +184,7 @@ elementtree_traverse(PyObject *m, visitproc visit, void *arg)
static void
elementtree_free(void *m)
{
elementtree_clear((PyObject *)m);
(void)elementtree_clear((PyObject *)m);
}
/* helpers */
@ -257,6 +257,7 @@ typedef struct {
} ElementObject;
#define _Element_CAST(op) ((ElementObject *)(op))
#define Element_CheckExact(st, op) Py_IS_TYPE(op, (st)->Element_Type)
#define Element_Check(st, op) PyObject_TypeCheck(op, (st)->Element_Type)
@ -648,8 +649,9 @@ subelement(PyObject *self, PyObject *args, PyObject *kwds)
}
static int
element_gc_traverse(ElementObject *self, visitproc visit, void *arg)
element_gc_traverse(PyObject *op, visitproc visit, void *arg)
{
ElementObject *self = _Element_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->tag);
Py_VISIT(JOIN_OBJ(self->text));
@ -666,8 +668,9 @@ element_gc_traverse(ElementObject *self, visitproc visit, void *arg)
}
static int
element_gc_clear(ElementObject *self)
element_gc_clear(PyObject *op)
{
ElementObject *self = _Element_CAST(op);
Py_CLEAR(self->tag);
_clear_joined_ptr(&self->text);
_clear_joined_ptr(&self->tail);
@ -680,8 +683,9 @@ element_gc_clear(ElementObject *self)
}
static void
element_dealloc(ElementObject* self)
element_dealloc(PyObject *op)
{
ElementObject *self = _Element_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
/* bpo-31095: UnTrack is needed before calling any callbacks */
@ -689,13 +693,13 @@ element_dealloc(ElementObject* self)
Py_TRASHCAN_BEGIN(self, element_dealloc)
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
PyObject_ClearWeakRefs(op);
/* element_gc_clear clears all references and deallocates extra
*/
element_gc_clear(self);
(void)element_gc_clear(op);
tp->tp_free((PyObject *)self);
tp->tp_free(self);
Py_DECREF(tp);
Py_TRASHCAN_END
}
@ -1478,9 +1482,9 @@ _elementtree_Element_itertext_impl(ElementObject *self, PyTypeObject *cls)
static PyObject*
element_getitem(PyObject* self_, Py_ssize_t index)
element_getitem(PyObject *op, Py_ssize_t index)
{
ElementObject* self = (ElementObject*) self_;
ElementObject *self = _Element_CAST(op);
if (!self->extra || index < 0 || index >= self->extra->length) {
PyErr_SetString(
@ -1494,9 +1498,9 @@ element_getitem(PyObject* self_, Py_ssize_t index)
}
static int
element_bool(PyObject* self_)
element_bool(PyObject *op)
{
ElementObject* self = (ElementObject*) self_;
ElementObject *self = _Element_CAST(op);
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"Testing an element's truth value will always return True "
"in future versions. Use specific 'len(elem)' or "
@ -1583,8 +1587,9 @@ _elementtree_Element_keys_impl(ElementObject *self)
}
static Py_ssize_t
element_length(ElementObject* self)
element_length(PyObject *op)
{
ElementObject *self = _Element_CAST(op);
if (!self->extra)
return 0;
@ -1675,10 +1680,10 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement)
}
static PyObject*
element_repr(ElementObject* self)
element_repr(PyObject *op)
{
int status;
ElementObject *self = _Element_CAST(op);
if (self->tag == NULL)
return PyUnicode_FromFormat("<Element at %p>", self);
@ -1728,9 +1733,9 @@ _elementtree_Element_set_impl(ElementObject *self, PyObject *key,
}
static int
element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
element_setitem(PyObject *op, Py_ssize_t index, PyObject* item)
{
ElementObject* self = (ElementObject*) self_;
ElementObject *self = _Element_CAST(op);
Py_ssize_t i;
PyObject* old;
@ -1762,10 +1767,10 @@ element_setitem(PyObject* self_, Py_ssize_t index, PyObject* item)
return 0;
}
static PyObject*
element_subscr(PyObject* self_, PyObject* item)
static PyObject *
element_subscr(PyObject *op, PyObject *item)
{
ElementObject* self = (ElementObject*) self_;
ElementObject *self = _Element_CAST(op);
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
@ -1775,7 +1780,7 @@ element_subscr(PyObject* self_, PyObject* item)
}
if (i < 0 && self->extra)
i += self->extra->length;
return element_getitem(self_, i);
return element_getitem(op, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen, i;
@ -1815,9 +1820,9 @@ element_subscr(PyObject* self_, PyObject* item)
}
static int
element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
{
ElementObject* self = (ElementObject*) self_;
ElementObject *self = _Element_CAST(op);
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
@ -1827,7 +1832,7 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
if (i < 0 && self->extra)
i += self->extra->length;
return element_setitem(self_, i, value);
return element_setitem(op, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen, newlen, i;
@ -1998,30 +2003,34 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
static PyObject*
element_tag_getter(ElementObject *self, void *closure)
element_tag_getter(PyObject *op, void *closure)
{
ElementObject *self = _Element_CAST(op);
PyObject *res = self->tag;
return Py_NewRef(res);
}
static PyObject*
element_text_getter(ElementObject *self, void *closure)
element_text_getter(PyObject *op, void *closure)
{
ElementObject *self = _Element_CAST(op);
PyObject *res = element_get_text(self);
return Py_XNewRef(res);
}
static PyObject*
element_tail_getter(ElementObject *self, void *closure)
element_tail_getter(PyObject *op, void *closure)
{
ElementObject *self = _Element_CAST(op);
PyObject *res = element_get_tail(self);
return Py_XNewRef(res);
}
static PyObject*
element_attrib_getter(ElementObject *self, void *closure)
element_attrib_getter(PyObject *op, void *closure)
{
PyObject *res;
ElementObject *self = _Element_CAST(op);
if (!self->extra) {
if (create_extra(self, NULL) < 0)
return NULL;
@ -2040,31 +2049,34 @@ element_attrib_getter(ElementObject *self, void *closure)
}
static int
element_tag_setter(ElementObject *self, PyObject *value, void *closure)
element_tag_setter(PyObject *op, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
ElementObject *self = _Element_CAST(op);
Py_SETREF(self->tag, Py_NewRef(value));
return 0;
}
static int
element_text_setter(ElementObject *self, PyObject *value, void *closure)
element_text_setter(PyObject *op, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
ElementObject *self = _Element_CAST(op);
_set_joined_ptr(&self->text, Py_NewRef(value));
return 0;
}
static int
element_tail_setter(ElementObject *self, PyObject *value, void *closure)
element_tail_setter(PyObject *op, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
ElementObject *self = _Element_CAST(op);
_set_joined_ptr(&self->tail, Py_NewRef(value));
return 0;
}
static int
element_attrib_setter(ElementObject *self, PyObject *value, void *closure)
element_attrib_setter(PyObject *op, PyObject *value, void *closure)
{
_VALIDATE_ATTR_VALUE(value);
if (!PyDict_Check(value)) {
@ -2073,6 +2085,7 @@ element_attrib_setter(ElementObject *self, PyObject *value, void *closure)
Py_TYPE(value)->tp_name);
return -1;
}
ElementObject *self = _Element_CAST(op);
if (!self->extra) {
if (create_extra(self, NULL) < 0)
return -1;
@ -2106,11 +2119,14 @@ typedef struct {
int gettext;
} ElementIterObject;
#define _ElementIter_CAST(op) ((ElementIterObject *)(op))
static void
elementiter_dealloc(ElementIterObject *it)
elementiter_dealloc(PyObject *op)
{
PyTypeObject *tp = Py_TYPE(it);
PyTypeObject *tp = Py_TYPE(op);
ElementIterObject *it = _ElementIter_CAST(op);
Py_ssize_t i = it->parent_stack_used;
it->parent_stack_used = 0;
/* bpo-31095: UnTrack is needed before calling any callbacks */
@ -2127,8 +2143,9 @@ elementiter_dealloc(ElementIterObject *it)
}
static int
elementiter_traverse(ElementIterObject *it, visitproc visit, void *arg)
elementiter_traverse(PyObject *op, visitproc visit, void *arg)
{
ElementIterObject *it = _ElementIter_CAST(op);
Py_ssize_t i = it->parent_stack_used;
while (i--)
Py_VISIT(it->parent_stack[i].parent);
@ -2162,8 +2179,9 @@ parent_stack_push_new(ElementIterObject *it, ElementObject *parent)
}
static PyObject *
elementiter_next(ElementIterObject *it)
elementiter_next(PyObject *op)
{
ElementIterObject *it = _ElementIter_CAST(op);
/* Sub-element iterator.
*
* A short note on gettext: this function serves both the iter() and
@ -2354,6 +2372,8 @@ typedef struct {
elementtreestate *state;
} TreeBuilderObject;
#define _TreeBuilder_CAST(op) ((TreeBuilderObject *)(op))
#define TreeBuilder_CheckExact(st, op) Py_IS_TYPE((op), (st)->TreeBuilder_Type)
/* -------------------------------------------------------------------- */
@ -2444,8 +2464,9 @@ _elementtree_TreeBuilder___init___impl(TreeBuilderObject *self,
}
static int
treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
treebuilder_gc_traverse(PyObject *op, visitproc visit, void *arg)
{
TreeBuilderObject *self = _TreeBuilder_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->pi_event_obj);
Py_VISIT(self->comment_event_obj);
@ -2467,8 +2488,9 @@ treebuilder_gc_traverse(TreeBuilderObject *self, visitproc visit, void *arg)
}
static int
treebuilder_gc_clear(TreeBuilderObject *self)
treebuilder_gc_clear(PyObject *op)
{
TreeBuilderObject *self = _TreeBuilder_CAST(op);
Py_CLEAR(self->pi_event_obj);
Py_CLEAR(self->comment_event_obj);
Py_CLEAR(self->end_ns_event_obj);
@ -2489,11 +2511,11 @@ treebuilder_gc_clear(TreeBuilderObject *self)
}
static void
treebuilder_dealloc(TreeBuilderObject *self)
treebuilder_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
treebuilder_gc_clear(self);
(void)treebuilder_gc_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -3061,6 +3083,9 @@ typedef struct {
PyObject *elementtree_module;
} XMLParserObject;
#define _XMLParser_CAST(op) ((XMLParserObject *)(op))
/* helpers */
LOCAL(PyObject*)
@ -3751,8 +3776,9 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
}
static int
xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
xmlparser_gc_traverse(PyObject *op, visitproc visit, void *arg)
{
XMLParserObject *self = _XMLParser_CAST(op);
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->handle_close);
Py_VISIT(self->handle_pi);
@ -3772,8 +3798,9 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg)
}
static int
xmlparser_gc_clear(XMLParserObject *self)
xmlparser_gc_clear(PyObject *op)
{
XMLParserObject *self = _XMLParser_CAST(op);
elementtreestate *st = self->state;
if (self->parser != NULL) {
XML_Parser parser = self->parser;
@ -3800,11 +3827,11 @@ xmlparser_gc_clear(XMLParserObject *self)
}
static void
xmlparser_dealloc(XMLParserObject* self)
xmlparser_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
xmlparser_gc_clear(self);
(void)xmlparser_gc_clear(self);
tp->tp_free(self);
Py_DECREF(tp);
}
@ -4172,7 +4199,7 @@ static PyMemberDef xmlparser_members[] = {
};
static PyObject*
xmlparser_version_getter(XMLParserObject *self, void *closure)
xmlparser_version_getter(PyObject *op, void *closure)
{
return PyUnicode_FromFormat(
"Expat %d.%d.%d", XML_MAJOR_VERSION,
@ -4180,7 +4207,7 @@ xmlparser_version_getter(XMLParserObject *self, void *closure)
}
static PyGetSetDef xmlparser_getsetlist[] = {
{"version", (getter)xmlparser_version_getter, NULL, NULL},
{"version", xmlparser_version_getter, NULL, NULL},
{NULL},
};
@ -4229,20 +4256,20 @@ static struct PyMemberDef element_members[] = {
static PyGetSetDef element_getsetlist[] = {
{"tag",
(getter)element_tag_getter,
(setter)element_tag_setter,
element_tag_getter,
element_tag_setter,
"A string identifying what kind of data this element represents"},
{"text",
(getter)element_text_getter,
(setter)element_text_setter,
element_text_getter,
element_text_setter,
"A string of text directly after the start tag, or None"},
{"tail",
(getter)element_tail_getter,
(setter)element_tail_setter,
element_tail_getter,
element_tail_setter,
"A string of text directly after the end tag, or None"},
{"attrib",
(getter)element_attrib_getter,
(setter)element_attrib_setter,
element_attrib_getter,
element_attrib_setter,
"A dictionary containing the element's attributes"},
{NULL},
};