gh-111178: fix UBSan failures in Objects/enumobject.c (GH-128246)

* fix UBSan failures for `enumobject`
* fix UBSan failures for `reversedobject`
This commit is contained in:
Bénédikt Tran 2025-01-03 15:29:41 +01:00 committed by GitHub
parent 621d4ff35e
commit aad5ba4b6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -23,6 +23,7 @@ typedef struct {
PyObject* one; /* borrowed reference */ PyObject* one; /* borrowed reference */
} enumobject; } enumobject;
#define _enumobject_CAST(op) ((enumobject *)(op))
/*[clinic input] /*[clinic input]
@classmethod @classmethod
@ -150,8 +151,9 @@ enumerate_vectorcall(PyObject *type, PyObject *const *args,
} }
static void static void
enum_dealloc(enumobject *en) enum_dealloc(PyObject *op)
{ {
enumobject *en = _enumobject_CAST(op);
PyObject_GC_UnTrack(en); PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit); Py_XDECREF(en->en_sit);
Py_XDECREF(en->en_result); Py_XDECREF(en->en_result);
@ -160,8 +162,9 @@ enum_dealloc(enumobject *en)
} }
static int static int
enum_traverse(enumobject *en, visitproc visit, void *arg) enum_traverse(PyObject *op, visitproc visit, void *arg)
{ {
enumobject *en = _enumobject_CAST(op);
Py_VISIT(en->en_sit); Py_VISIT(en->en_sit);
Py_VISIT(en->en_result); Py_VISIT(en->en_result);
Py_VISIT(en->en_longindex); Py_VISIT(en->en_longindex);
@ -220,8 +223,9 @@ enum_next_long(enumobject *en, PyObject* next_item)
} }
static PyObject * static PyObject *
enum_next(enumobject *en) enum_next(PyObject *op)
{ {
enumobject *en = _enumobject_CAST(op);
PyObject *next_index; PyObject *next_index;
PyObject *next_item; PyObject *next_item;
PyObject *result = en->en_result; PyObject *result = en->en_result;
@ -270,8 +274,9 @@ enum_next(enumobject *en)
} }
static PyObject * static PyObject *
enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored)) enum_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
enumobject *en = _enumobject_CAST(op);
if (en->en_longindex != NULL) if (en->en_longindex != NULL)
return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex); return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
else else
@ -281,7 +286,7 @@ enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyMethodDef enum_methods[] = { static PyMethodDef enum_methods[] = {
{"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc}, {"__reduce__", enum_reduce, METH_NOARGS, reduce_doc},
{"__class_getitem__", Py_GenericAlias, {"__class_getitem__", Py_GenericAlias,
METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
@ -293,7 +298,7 @@ PyTypeObject PyEnum_Type = {
sizeof(enumobject), /* tp_basicsize */ sizeof(enumobject), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
/* methods */ /* methods */
(destructor)enum_dealloc, /* tp_dealloc */ enum_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
@ -311,12 +316,12 @@ PyTypeObject PyEnum_Type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_BASETYPE, /* tp_flags */
enum_new__doc__, /* tp_doc */ enum_new__doc__, /* tp_doc */
(traverseproc)enum_traverse, /* tp_traverse */ enum_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */ PyObject_SelfIter, /* tp_iter */
(iternextfunc)enum_next, /* tp_iternext */ enum_next, /* tp_iternext */
enum_methods, /* tp_methods */ enum_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
@ -329,7 +334,7 @@ PyTypeObject PyEnum_Type = {
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
enum_new, /* tp_new */ enum_new, /* tp_new */
PyObject_GC_Del, /* tp_free */ PyObject_GC_Del, /* tp_free */
.tp_vectorcall = (vectorcallfunc)enumerate_vectorcall .tp_vectorcall = enumerate_vectorcall
}; };
/* Reversed Object ***************************************************************/ /* Reversed Object ***************************************************************/
@ -340,6 +345,8 @@ typedef struct {
PyObject* seq; PyObject* seq;
} reversedobject; } reversedobject;
#define _reversedobject_CAST(op) ((reversedobject *)(op))
/*[clinic input] /*[clinic input]
@classmethod @classmethod
reversed.__new__ as reversed_new reversed.__new__ as reversed_new
@ -411,23 +418,26 @@ reversed_vectorcall(PyObject *type, PyObject * const*args,
} }
static void static void
reversed_dealloc(reversedobject *ro) reversed_dealloc(PyObject *op)
{ {
reversedobject *ro = _reversedobject_CAST(op);
PyObject_GC_UnTrack(ro); PyObject_GC_UnTrack(ro);
Py_XDECREF(ro->seq); Py_XDECREF(ro->seq);
Py_TYPE(ro)->tp_free(ro); Py_TYPE(ro)->tp_free(ro);
} }
static int static int
reversed_traverse(reversedobject *ro, visitproc visit, void *arg) reversed_traverse(PyObject *op, visitproc visit, void *arg)
{ {
reversedobject *ro = _reversedobject_CAST(op);
Py_VISIT(ro->seq); Py_VISIT(ro->seq);
return 0; return 0;
} }
static PyObject * static PyObject *
reversed_next(reversedobject *ro) reversed_next(PyObject *op)
{ {
reversedobject *ro = _reversedobject_CAST(op);
PyObject *item; PyObject *item;
Py_ssize_t index = ro->index; Py_ssize_t index = ro->index;
@ -447,8 +457,9 @@ reversed_next(reversedobject *ro)
} }
static PyObject * static PyObject *
reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored)) reversed_len(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
reversedobject *ro = _reversedobject_CAST(op);
Py_ssize_t position, seqsize; Py_ssize_t position, seqsize;
if (ro->seq == NULL) if (ro->seq == NULL)
@ -463,8 +474,9 @@ reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
static PyObject * static PyObject *
reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored)) reversed_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{ {
reversedobject *ro = _reversedobject_CAST(op);
if (ro->seq) if (ro->seq)
return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index); return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
else else
@ -472,8 +484,9 @@ reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored))
} }
static PyObject * static PyObject *
reversed_setstate(reversedobject *ro, PyObject *state) reversed_setstate(PyObject *op, PyObject *state)
{ {
reversedobject *ro = _reversedobject_CAST(op);
Py_ssize_t index = PyLong_AsSsize_t(state); Py_ssize_t index = PyLong_AsSsize_t(state);
if (index == -1 && PyErr_Occurred()) if (index == -1 && PyErr_Occurred())
return NULL; return NULL;
@ -493,9 +506,9 @@ reversed_setstate(reversedobject *ro, PyObject *state)
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
static PyMethodDef reversediter_methods[] = { static PyMethodDef reversediter_methods[] = {
{"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc}, {"__length_hint__", reversed_len, METH_NOARGS, length_hint_doc},
{"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc}, {"__reduce__", reversed_reduce, METH_NOARGS, reduce_doc},
{"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc}, {"__setstate__", reversed_setstate, METH_O, setstate_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
@ -505,7 +518,7 @@ PyTypeObject PyReversed_Type = {
sizeof(reversedobject), /* tp_basicsize */ sizeof(reversedobject), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
/* methods */ /* methods */
(destructor)reversed_dealloc, /* tp_dealloc */ reversed_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */ 0, /* tp_vectorcall_offset */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
@ -523,12 +536,12 @@ PyTypeObject PyReversed_Type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_BASETYPE, /* tp_flags */
reversed_new__doc__, /* tp_doc */ reversed_new__doc__, /* tp_doc */
(traverseproc)reversed_traverse,/* tp_traverse */ reversed_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */ PyObject_SelfIter, /* tp_iter */
(iternextfunc)reversed_next, /* tp_iternext */ reversed_next, /* tp_iternext */
reversediter_methods, /* tp_methods */ reversediter_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
@ -541,5 +554,5 @@ PyTypeObject PyReversed_Type = {
PyType_GenericAlloc, /* tp_alloc */ PyType_GenericAlloc, /* tp_alloc */
reversed_new, /* tp_new */ reversed_new, /* tp_new */
PyObject_GC_Del, /* tp_free */ PyObject_GC_Del, /* tp_free */
.tp_vectorcall = (vectorcallfunc)reversed_vectorcall, .tp_vectorcall = reversed_vectorcall,
}; };