mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
gh-111178: fix UBSan failures in Modules/_operator.c
(GH-129785)
Fix UBSan failures for `itemgetterobject`, `attrgetterobject`, `methodcallerobject` Suppress unused return values
This commit is contained in:
parent
e24a1ac17c
commit
4466e91360
1 changed files with 77 additions and 54 deletions
|
@ -999,13 +999,13 @@ static struct PyMethodDef operator_methods[] = {
|
|||
|
||||
|
||||
static PyObject *
|
||||
text_signature(PyObject *self, void *Py_UNUSED(ignored))
|
||||
text_signature(PyObject *Py_UNUSED(self), void *Py_UNUSED(closure))
|
||||
{
|
||||
return PyUnicode_FromString("(obj, /)");
|
||||
}
|
||||
|
||||
static PyGetSetDef common_getset[] = {
|
||||
{"__text_signature__", text_signature, (setter)NULL},
|
||||
{"__text_signature__", text_signature, NULL},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
@ -1019,6 +1019,8 @@ typedef struct {
|
|||
vectorcallfunc vectorcall;
|
||||
} itemgetterobject;
|
||||
|
||||
#define itemgetterobject_CAST(op) ((itemgetterobject *)(op))
|
||||
|
||||
// Forward declarations
|
||||
static PyObject *
|
||||
itemgetter_vectorcall(PyObject *, PyObject *const *, size_t, PyObject *);
|
||||
|
@ -1069,49 +1071,52 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
}
|
||||
}
|
||||
|
||||
ig->vectorcall = (vectorcallfunc)itemgetter_vectorcall;
|
||||
ig->vectorcall = itemgetter_vectorcall;
|
||||
PyObject_GC_Track(ig);
|
||||
return (PyObject *)ig;
|
||||
}
|
||||
|
||||
static int
|
||||
itemgetter_clear(itemgetterobject *ig)
|
||||
itemgetter_clear(PyObject *op)
|
||||
{
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
Py_CLEAR(ig->item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
itemgetter_dealloc(itemgetterobject *ig)
|
||||
itemgetter_dealloc(PyObject *op)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(ig);
|
||||
PyObject_GC_UnTrack(ig);
|
||||
(void)itemgetter_clear(ig);
|
||||
tp->tp_free(ig);
|
||||
PyTypeObject *tp = Py_TYPE(op);
|
||||
PyObject_GC_UnTrack(op);
|
||||
(void)itemgetter_clear(op);
|
||||
tp->tp_free(op);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static int
|
||||
itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
|
||||
itemgetter_traverse(PyObject *op, visitproc visit, void *arg)
|
||||
{
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
Py_VISIT(Py_TYPE(ig));
|
||||
Py_VISIT(ig->item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
|
||||
itemgetter_call(PyObject *op, PyObject *args, PyObject *kw)
|
||||
{
|
||||
assert(PyTuple_CheckExact(args));
|
||||
if (!_PyArg_NoKeywords("itemgetter", kw))
|
||||
return NULL;
|
||||
if (!_PyArg_CheckPositional("itemgetter", PyTuple_GET_SIZE(args), 1, 1))
|
||||
return NULL;
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
return itemgetter_call_impl(ig, PyTuple_GET_ITEM(args, 0));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
itemgetter_vectorcall(PyObject *ig, PyObject *const *args,
|
||||
itemgetter_vectorcall(PyObject *op, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
if (!_PyArg_NoKwnames("itemgetter", kwnames)) {
|
||||
|
@ -1121,7 +1126,8 @@ itemgetter_vectorcall(PyObject *ig, PyObject *const *args,
|
|||
if (!_PyArg_CheckPositional("itemgetter", nargs, 1, 1)) {
|
||||
return NULL;
|
||||
}
|
||||
return itemgetter_call_impl((itemgetterobject *)ig, args[0]);
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
return itemgetter_call_impl(ig, args[0]);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -1161,12 +1167,13 @@ itemgetter_call_impl(itemgetterobject *ig, PyObject *obj)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
itemgetter_repr(itemgetterobject *ig)
|
||||
itemgetter_repr(PyObject *op)
|
||||
{
|
||||
PyObject *repr;
|
||||
const char *reprfmt;
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
|
||||
int status = Py_ReprEnter((PyObject *)ig);
|
||||
int status = Py_ReprEnter(op);
|
||||
if (status != 0) {
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
|
@ -1175,13 +1182,14 @@ itemgetter_repr(itemgetterobject *ig)
|
|||
|
||||
reprfmt = ig->nitems == 1 ? "%s(%R)" : "%s%R";
|
||||
repr = PyUnicode_FromFormat(reprfmt, Py_TYPE(ig)->tp_name, ig->item);
|
||||
Py_ReprLeave((PyObject *)ig);
|
||||
Py_ReprLeave(op);
|
||||
return repr;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
itemgetter_reduce(itemgetterobject *ig, PyObject *Py_UNUSED(ignored))
|
||||
itemgetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy))
|
||||
{
|
||||
itemgetterobject *ig = itemgetterobject_CAST(op);
|
||||
if (ig->nitems == 1)
|
||||
return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item);
|
||||
return PyTuple_Pack(2, Py_TYPE(ig), ig->item);
|
||||
|
@ -1190,7 +1198,7 @@ itemgetter_reduce(itemgetterobject *ig, PyObject *Py_UNUSED(ignored))
|
|||
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
|
||||
|
||||
static PyMethodDef itemgetter_methods[] = {
|
||||
{"__reduce__", (PyCFunction)itemgetter_reduce, METH_NOARGS,
|
||||
{"__reduce__", itemgetter_reduce, METH_NOARGS,
|
||||
reduce_doc},
|
||||
{NULL}
|
||||
};
|
||||
|
@ -1239,6 +1247,8 @@ typedef struct {
|
|||
vectorcallfunc vectorcall;
|
||||
} attrgetterobject;
|
||||
|
||||
#define attrgetterobject_CAST(op) ((attrgetterobject *)(op))
|
||||
|
||||
// Forward declarations
|
||||
static PyObject *
|
||||
attrgetter_vectorcall(PyObject *, PyObject *const *, size_t, PyObject *);
|
||||
|
@ -1348,32 +1358,34 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
|
||||
ag->attr = attr;
|
||||
ag->nattrs = nattrs;
|
||||
ag->vectorcall = (vectorcallfunc)attrgetter_vectorcall;
|
||||
ag->vectorcall = attrgetter_vectorcall;
|
||||
|
||||
PyObject_GC_Track(ag);
|
||||
return (PyObject *)ag;
|
||||
}
|
||||
|
||||
static int
|
||||
attrgetter_clear(attrgetterobject *ag)
|
||||
attrgetter_clear(PyObject *op)
|
||||
{
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
Py_CLEAR(ag->attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
attrgetter_dealloc(attrgetterobject *ag)
|
||||
attrgetter_dealloc(PyObject *op)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(ag);
|
||||
PyObject_GC_UnTrack(ag);
|
||||
(void)attrgetter_clear(ag);
|
||||
tp->tp_free(ag);
|
||||
PyTypeObject *tp = Py_TYPE(op);
|
||||
PyObject_GC_UnTrack(op);
|
||||
(void)attrgetter_clear(op);
|
||||
tp->tp_free(op);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static int
|
||||
attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
|
||||
attrgetter_traverse(PyObject *op, visitproc visit, void *arg)
|
||||
{
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
Py_VISIT(ag->attr);
|
||||
Py_VISIT(Py_TYPE(ag));
|
||||
return 0;
|
||||
|
@ -1413,17 +1425,19 @@ dotted_getattr(PyObject *obj, PyObject *attr)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
|
||||
attrgetter_call(PyObject *op, PyObject *args, PyObject *kw)
|
||||
{
|
||||
if (!_PyArg_NoKeywords("attrgetter", kw))
|
||||
return NULL;
|
||||
if (!_PyArg_CheckPositional("attrgetter", PyTuple_GET_SIZE(args), 1, 1))
|
||||
return NULL;
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
return attrgetter_call_impl(ag, PyTuple_GET_ITEM(args, 0));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
attrgetter_vectorcall(PyObject *ag, PyObject *const *args, size_t nargsf, PyObject *kwnames)
|
||||
attrgetter_vectorcall(PyObject *op, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
if (!_PyArg_NoKwnames("attrgetter", kwnames)) {
|
||||
return NULL;
|
||||
|
@ -1432,7 +1446,8 @@ attrgetter_vectorcall(PyObject *ag, PyObject *const *args, size_t nargsf, PyObje
|
|||
if (!_PyArg_CheckPositional("attrgetter", nargs, 1, 1)) {
|
||||
return NULL;
|
||||
}
|
||||
return attrgetter_call_impl((attrgetterobject *)ag, args[0]);
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
return attrgetter_call_impl(ag, args[0]);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -1505,10 +1520,11 @@ attrgetter_args(attrgetterobject *ag)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
attrgetter_repr(attrgetterobject *ag)
|
||||
attrgetter_repr(PyObject *op)
|
||||
{
|
||||
PyObject *repr = NULL;
|
||||
int status = Py_ReprEnter((PyObject *)ag);
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
int status = Py_ReprEnter(op);
|
||||
if (status != 0) {
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
|
@ -1532,22 +1548,22 @@ attrgetter_repr(attrgetterobject *ag)
|
|||
Py_DECREF(attrstrings);
|
||||
}
|
||||
}
|
||||
Py_ReprLeave((PyObject *)ag);
|
||||
Py_ReprLeave(op);
|
||||
return repr;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
attrgetter_reduce(attrgetterobject *ag, PyObject *Py_UNUSED(ignored))
|
||||
attrgetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy))
|
||||
{
|
||||
attrgetterobject *ag = attrgetterobject_CAST(op);
|
||||
PyObject *attrstrings = attrgetter_args(ag);
|
||||
if (attrstrings == NULL)
|
||||
return NULL;
|
||||
|
||||
return Py_BuildValue("ON", Py_TYPE(ag), attrstrings);
|
||||
}
|
||||
|
||||
static PyMethodDef attrgetter_methods[] = {
|
||||
{"__reduce__", (PyCFunction)attrgetter_reduce, METH_NOARGS,
|
||||
{"__reduce__", attrgetter_reduce, METH_NOARGS,
|
||||
reduce_doc},
|
||||
{NULL}
|
||||
};
|
||||
|
@ -1602,13 +1618,15 @@ typedef struct {
|
|||
vectorcallfunc vectorcall;
|
||||
} methodcallerobject;
|
||||
|
||||
#define methodcallerobject_CAST(op) ((methodcallerobject *)(op))
|
||||
|
||||
#define _METHODCALLER_MAX_ARGS 8
|
||||
|
||||
static PyObject *
|
||||
methodcaller_vectorcall(methodcallerobject *mc, PyObject *const *args,
|
||||
size_t nargsf, PyObject* kwnames)
|
||||
methodcaller_vectorcall(PyObject *op, PyObject *const *args,
|
||||
size_t nargsf, PyObject* kwnames)
|
||||
{
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
if (!_PyArg_CheckPositional("methodcaller", PyVectorcall_NARGS(nargsf), 1, 1)
|
||||
|| !_PyArg_NoKwnames("methodcaller", kwnames)) {
|
||||
return NULL;
|
||||
|
@ -1661,7 +1679,7 @@ _methodcaller_initialize_vectorcall(methodcallerobject* mc)
|
|||
mc->vectorcall_kwnames = NULL;
|
||||
}
|
||||
|
||||
mc->vectorcall = (vectorcallfunc)methodcaller_vectorcall;
|
||||
mc->vectorcall = methodcaller_vectorcall;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1721,8 +1739,9 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
}
|
||||
|
||||
static void
|
||||
methodcaller_clear(methodcallerobject *mc)
|
||||
methodcaller_clear(PyObject *op)
|
||||
{
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
Py_CLEAR(mc->name);
|
||||
Py_CLEAR(mc->args);
|
||||
Py_CLEAR(mc->kwds);
|
||||
|
@ -1731,18 +1750,19 @@ methodcaller_clear(methodcallerobject *mc)
|
|||
}
|
||||
|
||||
static void
|
||||
methodcaller_dealloc(methodcallerobject *mc)
|
||||
methodcaller_dealloc(PyObject *op)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(mc);
|
||||
PyObject_GC_UnTrack(mc);
|
||||
methodcaller_clear(mc);
|
||||
tp->tp_free(mc);
|
||||
PyTypeObject *tp = Py_TYPE(op);
|
||||
PyObject_GC_UnTrack(op);
|
||||
(void)methodcaller_clear(op);
|
||||
tp->tp_free(op);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static int
|
||||
methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
|
||||
methodcaller_traverse(PyObject *op, visitproc visit, void *arg)
|
||||
{
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
Py_VISIT(mc->name);
|
||||
Py_VISIT(mc->args);
|
||||
Py_VISIT(mc->kwds);
|
||||
|
@ -1753,9 +1773,10 @@ methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
|
||||
methodcaller_call(PyObject *op, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *method, *obj, *result;
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
|
||||
if (!_PyArg_NoKeywords("methodcaller", kw))
|
||||
return NULL;
|
||||
|
@ -1772,11 +1793,12 @@ methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
methodcaller_repr(methodcallerobject *mc)
|
||||
methodcaller_repr(PyObject *op)
|
||||
{
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
PyObject *argreprs, *repr = NULL, *sep, *joinedargreprs;
|
||||
Py_ssize_t numtotalargs, numposargs, numkwdargs, i;
|
||||
int status = Py_ReprEnter((PyObject *)mc);
|
||||
int status = Py_ReprEnter(op);
|
||||
if (status != 0) {
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
|
@ -1789,13 +1811,13 @@ methodcaller_repr(methodcallerobject *mc)
|
|||
|
||||
if (numtotalargs == 0) {
|
||||
repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(mc)->tp_name, mc->name);
|
||||
Py_ReprLeave((PyObject *)mc);
|
||||
Py_ReprLeave(op);
|
||||
return repr;
|
||||
}
|
||||
|
||||
argreprs = PyTuple_New(numtotalargs);
|
||||
if (argreprs == NULL) {
|
||||
Py_ReprLeave((PyObject *)mc);
|
||||
Py_ReprLeave(op);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1843,13 +1865,14 @@ methodcaller_repr(methodcallerobject *mc)
|
|||
|
||||
done:
|
||||
Py_DECREF(argreprs);
|
||||
Py_ReprLeave((PyObject *)mc);
|
||||
Py_ReprLeave(op);
|
||||
return repr;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
|
||||
methodcaller_reduce(PyObject *op, PyObject *Py_UNUSED(dummy))
|
||||
{
|
||||
methodcallerobject *mc = methodcallerobject_CAST(op);
|
||||
if (!mc->kwds || PyDict_GET_SIZE(mc->kwds) == 0) {
|
||||
Py_ssize_t i;
|
||||
Py_ssize_t callargcount = PyTuple_GET_SIZE(mc->args);
|
||||
|
@ -1882,7 +1905,7 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
static PyMethodDef methodcaller_methods[] = {
|
||||
{"__reduce__", (PyCFunction)methodcaller_reduce, METH_NOARGS,
|
||||
{"__reduce__", methodcaller_reduce, METH_NOARGS,
|
||||
reduce_doc},
|
||||
{NULL}
|
||||
};
|
||||
|
@ -1985,7 +2008,7 @@ operator_clear(PyObject *module)
|
|||
static void
|
||||
operator_free(void *module)
|
||||
{
|
||||
operator_clear((PyObject *)module);
|
||||
(void)operator_clear((PyObject *)module);
|
||||
}
|
||||
|
||||
static struct PyModuleDef operatormodule = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue