From 22e4df825b78e8c9770062b5f92a7bf40609d7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:32:30 +0100 Subject: [PATCH 1/8] fix UBSan failures for `dequeobject` --- Modules/_collectionsmodule.c | 74 ++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index aef04248c7e73c..c5dc7c80dcb31b 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -144,6 +144,8 @@ struct dequeobject { PyObject *weakreflist; }; +#define _dequeobject_CAST(op) ((dequeobject *)(op)) + /* For debug builds, add error checking to track the endpoints * in the chain of links. The goal is to make sure that link * assignments only take place at endpoints so that links already @@ -570,8 +572,9 @@ deque_extendleft_impl(dequeobject *deque, PyObject *iterable) } static PyObject * -deque_inplace_concat(dequeobject *deque, PyObject *other) +deque_inplace_concat(PyObject *self, PyObject *other) { + dequeobject *deque = _dequeobject_CAST(self); PyObject *result; // deque_extend is thread-safe @@ -597,14 +600,13 @@ deque_copy_impl(dequeobject *deque) /*[clinic end generated code: output=6409b3d1ad2898b5 input=51d2ed1a23bab5e2]*/ { PyObject *result; - dequeobject *old_deque = (dequeobject *)deque; + dequeobject *old_deque = deque; collections_state *state = find_module_state_by_def(Py_TYPE(deque)); if (Py_IS_TYPE(deque, state->deque_type)) { dequeobject *new_deque; PyObject *rv; - new_deque = (dequeobject *)deque_new(state->deque_type, - (PyObject *)NULL, (PyObject *)NULL); + new_deque = (dequeobject *)deque_new(state->deque_type, NULL, NULL); if (new_deque == NULL) return NULL; new_deque->maxlen = old_deque->maxlen; @@ -689,8 +691,9 @@ deque_concat_lock_held(dequeobject *deque, PyObject *other) } static PyObject * -deque_concat(dequeobject *deque, PyObject *other) +deque_concat(PyObject *self, PyObject *other) { + dequeobject *deque = _dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_concat_lock_held(deque, other); @@ -699,7 +702,7 @@ deque_concat(dequeobject *deque, PyObject *other) } static int -deque_clear(dequeobject *deque) +deque_clear(PyObject *self) { block *b; block *prevblock; @@ -708,6 +711,7 @@ deque_clear(dequeobject *deque) Py_ssize_t n, m; PyObject *item; PyObject **itemptr, **limit; + dequeobject *deque = _dequeobject_CAST(self); if (Py_SIZE(deque) == 0) return 0; @@ -795,7 +799,7 @@ static PyObject * deque_clearmethod_impl(dequeobject *deque) /*[clinic end generated code: output=79b2513e097615c1 input=3a22e9605d20c5e9]*/ { - deque_clear(deque); + (void)deque_clear((PyObject *)deque); Py_RETURN_NONE; } @@ -812,7 +816,7 @@ deque_inplace_repeat_lock_held(dequeobject *deque, Py_ssize_t n) } if (n <= 0) { - deque_clear(deque); + (void)deque_clear((PyObject *)deque); return Py_NewRef(deque); } @@ -877,8 +881,9 @@ deque_inplace_repeat_lock_held(dequeobject *deque, Py_ssize_t n) } static PyObject * -deque_inplace_repeat(dequeobject *deque, Py_ssize_t n) +deque_inplace_repeat(PyObject *self, Py_ssize_t n) { + dequeobject *deque = _dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_inplace_repeat_lock_held(deque, n); @@ -887,8 +892,9 @@ deque_inplace_repeat(dequeobject *deque, Py_ssize_t n) } static PyObject * -deque_repeat(dequeobject *deque, Py_ssize_t n) +deque_repeat(PyObject *self, Py_ssize_t n) { + dequeobject *deque = _dequeobject_CAST(self); dequeobject *new_deque; PyObject *rv; @@ -1202,8 +1208,9 @@ deque_contains_lock_held(dequeobject *deque, PyObject *v) } static int -deque_contains(dequeobject *deque, PyObject *v) +deque_contains(PyObject *self, PyObject *v) { + dequeobject *deque = _dequeobject_CAST(self); int result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_contains_lock_held(deque, v); @@ -1212,9 +1219,10 @@ deque_contains(dequeobject *deque, PyObject *v) } static Py_ssize_t -deque_len(dequeobject *deque) +deque_len(PyObject *self) { - return FT_ATOMIC_LOAD_SSIZE(((PyVarObject *)deque)->ob_size); + PyVarObject *deque = _PyVarObject_CAST(self); + return FT_ATOMIC_LOAD_SSIZE(deque->ob_size); } /*[clinic input] @@ -1394,8 +1402,9 @@ deque_item_lock_held(dequeobject *deque, Py_ssize_t i) } static PyObject * -deque_item(dequeobject *deque, Py_ssize_t i) +deque_item(PyObject *self, Py_ssize_t i) { + dequeobject *deque = _dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_item_lock_held(deque, i); @@ -1505,8 +1514,9 @@ deque_ass_item_lock_held(dequeobject *deque, Py_ssize_t i, PyObject *v) } static int -deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) +deque_ass_item(PyObject *self, Py_ssize_t i, PyObject *v) { + dequeobject *deque = _dequeobject_CAST(self); int result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_ass_item_lock_held(deque, i, v); @@ -1515,16 +1525,18 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) } static void -deque_dealloc(dequeobject *deque) +deque_dealloc(PyObject *self) { + dequeobject *deque = _dequeobject_CAST(self); PyTypeObject *tp = Py_TYPE(deque); Py_ssize_t i; PyObject_GC_UnTrack(deque); - if (deque->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) deque); + if (deque->weakreflist != NULL) { + PyObject_ClearWeakRefs(self); + } if (deque->leftblock != NULL) { - deque_clear(deque); + (void)deque_clear(self); assert(deque->leftblock != NULL); freeblock(deque, deque->leftblock); } @@ -1538,8 +1550,9 @@ deque_dealloc(dequeobject *deque) } static int -deque_traverse(dequeobject *deque, visitproc visit, void *arg) +deque_traverse(PyObject *self, visitproc visit, void *arg) { + dequeobject *deque = _dequeobject_CAST(self); Py_VISIT(Py_TYPE(deque)); block *b; @@ -1618,10 +1631,11 @@ deque_repr(PyObject *deque) Py_ReprLeave(deque); return NULL; } - if (((dequeobject *)deque)->maxlen >= 0) + Py_ssize_t maxlen = _dequeobject_CAST(deque)->maxlen; + if (maxlen >= 0) result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)", _PyType_Name(Py_TYPE(deque)), aslist, - ((dequeobject *)deque)->maxlen); + maxlen); else result = PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(deque)), aslist); @@ -1644,8 +1658,8 @@ deque_richcompare(PyObject *v, PyObject *w, int op) } /* Shortcuts */ - vs = Py_SIZE((dequeobject *)v); - ws = Py_SIZE((dequeobject *)w); + vs = Py_SIZE(v); + ws = Py_SIZE(w); if (op == Py_EQ) { if (v == w) Py_RETURN_TRUE; @@ -1737,7 +1751,7 @@ deque_init_impl(dequeobject *deque, PyObject *iterable, PyObject *maxlenobj) } deque->maxlen = maxlen; if (Py_SIZE(deque) > 0) - deque_clear(deque); + (void)deque_clear((PyObject *)deque); if (iterable != NULL) { PyObject *rv = deque_extend_impl(deque, iterable); if (rv == NULL) @@ -1770,8 +1784,9 @@ deque___sizeof___impl(dequeobject *deque) } static PyObject * -deque_get_maxlen(dequeobject *deque, void *Py_UNUSED(ignored)) +deque_get_maxlen(PyObject *self, void *Py_UNUSED(closure)) { + dequeobject *deque = _dequeobject_CAST(self); if (deque->maxlen < 0) Py_RETURN_NONE; return PyLong_FromSsize_t(deque->maxlen); @@ -1797,12 +1812,12 @@ deque___reversed___impl(dequeobject *deque) /* deque object ********************************************************/ static PyGetSetDef deque_getset[] = { - {"maxlen", (getter)deque_get_maxlen, (setter)NULL, + {"maxlen", deque_get_maxlen, NULL, "maximum size of a deque or None if unbounded"}, {0} }; -static PyObject *deque_iter(dequeobject *deque); +static PyObject *deque_iter(PyObject *deque); static PyMethodDef deque_methods[] = { DEQUE_APPEND_METHODDEF @@ -1884,9 +1899,10 @@ typedef struct { } dequeiterobject; static PyObject * -deque_iter(dequeobject *deque) +deque_iter(PyObject *self) { dequeiterobject *it; + dequeobject *deque = _dequeobject_CAST(self); collections_state *state = find_module_state_by_def(Py_TYPE(deque)); it = PyObject_GC_New(dequeiterobject, state->dequeiter_type); From a19302d3051c90efe5ce66d6b506233811ac552c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:38:00 +0100 Subject: [PATCH 2/8] fix UBSan failures for `dequeiterobject` --- Modules/_collectionsmodule.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c5dc7c80dcb31b..6ca12cae5d2951 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1898,6 +1898,8 @@ typedef struct { Py_ssize_t counter; /* number of items remaining for iteration */ } dequeiterobject; +#define _dequeiterobject_CAST(op) ((dequeiterobject *)(op)) + static PyObject * deque_iter(PyObject *self) { @@ -1920,22 +1922,24 @@ deque_iter(PyObject *self) } static int -dequeiter_traverse(dequeiterobject *dio, visitproc visit, void *arg) +dequeiter_traverse(PyObject *op, visitproc visit, void *arg) { + dequeiterobject *dio = _dequeiterobject_CAST(op); Py_VISIT(Py_TYPE(dio)); Py_VISIT(dio->deque); return 0; } static int -dequeiter_clear(dequeiterobject *dio) +dequeiter_clear(PyObject *op) { + dequeiterobject *dio = _dequeiterobject_CAST(op); Py_CLEAR(dio->deque); return 0; } static void -dequeiter_dealloc(dequeiterobject *dio) +dequeiter_dealloc(PyObject *dio) { /* bpo-31095: UnTrack is needed before calling any callbacks */ PyTypeObject *tp = Py_TYPE(dio); @@ -1973,9 +1977,10 @@ dequeiter_next_lock_held(dequeiterobject *it, dequeobject *deque) } static PyObject * -dequeiter_next(dequeiterobject *it) +dequeiter_next(PyObject *op) { PyObject *result; + dequeiterobject *it = _dequeiterobject_CAST(op); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. dequeobject *deque = it->deque; @@ -1997,12 +2002,12 @@ dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; assert(type == state->dequeiter_type); - it = (dequeiterobject*)deque_iter((dequeobject *)deque); + it = (dequeiterobject*)deque_iter(deque); if (!it) return NULL; /* consume items from the queue */ for(i=0; icounter); return PyLong_FromSsize_t(len); } @@ -2031,23 +2037,24 @@ dequeiter_len(dequeiterobject *it, PyObject *Py_UNUSED(ignored)) PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyObject * -dequeiter_reduce(dequeiterobject *it, PyObject *Py_UNUSED(ignored)) +dequeiter_reduce(PyObject *op, PyObject *Py_UNUSED(args)) { + dequeiterobject *it = _dequeiterobject_CAST(op); PyTypeObject *ty = Py_TYPE(it); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. dequeobject *deque = it->deque; Py_ssize_t size, counter; Py_BEGIN_CRITICAL_SECTION2(it, deque); - size = Py_SIZE(deque); + size = Py_SIZE((PyObject *)deque); counter = it->counter; Py_END_CRITICAL_SECTION2(); return Py_BuildValue("O(On)", ty, deque, size - counter); } static PyMethodDef dequeiter_methods[] = { - {"__length_hint__", (PyCFunction)dequeiter_len, METH_NOARGS, length_hint_doc}, - {"__reduce__", (PyCFunction)dequeiter_reduce, METH_NOARGS, reduce_doc}, + {"__length_hint__", dequeiter_len, METH_NOARGS, length_hint_doc}, + {"__reduce__", dequeiter_reduce, METH_NOARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; @@ -2121,9 +2128,10 @@ dequereviter_next_lock_held(dequeiterobject *it, dequeobject *deque) } static PyObject * -dequereviter_next(dequeiterobject *it) +dequereviter_next(PyObject *self) { PyObject *item; + dequeiterobject *it = _dequeiterobject_CAST(self); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. dequeobject *deque = it->deque; @@ -2149,7 +2157,7 @@ dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; /* consume items from the queue */ for(i=0; i Date: Sat, 25 Jan 2025 18:07:14 +0100 Subject: [PATCH 3/8] fix UBSan failures for `defdictobject` --- Modules/_collectionsmodule.c | 53 +++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 6ca12cae5d2951..d353b6780396b7 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2203,6 +2203,8 @@ typedef struct { PyObject *default_factory; } defdictobject; +#define _defdictobject_CAST(op) ((defdictobject *)(op)) + static PyType_Spec defdict_spec; PyDoc_STRVAR(defdict_missing_doc, @@ -2213,8 +2215,9 @@ PyDoc_STRVAR(defdict_missing_doc, "); static PyObject * -defdict_missing(defdictobject *dd, PyObject *key) +defdict_missing(PyObject *op, PyObject *key) { + defdictobject *dd = _defdictobject_CAST(op); PyObject *factory = dd->default_factory; PyObject *value; if (factory == NULL || factory == Py_None) { @@ -2229,7 +2232,7 @@ defdict_missing(defdictobject *dd, PyObject *key) value = _PyObject_CallNoArgs(factory); if (value == NULL) return value; - if (PyObject_SetItem((PyObject *)dd, key, value) < 0) { + if (PyObject_SetItem(op, key, value) < 0) { Py_DECREF(value); return NULL; } @@ -2237,8 +2240,9 @@ defdict_missing(defdictobject *dd, PyObject *key) } static inline PyObject* -new_defdict(defdictobject *dd, PyObject *arg) +new_defdict(PyObject *op, PyObject *arg) { + defdictobject *dd = _defdictobject_CAST(op); return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), dd->default_factory ? dd->default_factory : Py_None, arg, NULL); } @@ -2246,17 +2250,17 @@ new_defdict(defdictobject *dd, PyObject *arg) PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); static PyObject * -defdict_copy(defdictobject *dd, PyObject *Py_UNUSED(ignored)) +defdict_copy(PyObject *op, PyObject *Py_UNUSED(args)) { /* This calls the object's class. That only works for subclasses whose class constructor has the same signature. Subclasses that define a different constructor signature must override copy(). */ - return new_defdict(dd, (PyObject*)dd); + return new_defdict(op, op); } static PyObject * -defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored)) +defdict_reduce(PyObject *op, PyObject *Py_UNUSED(args)) { /* __reduce__ must return a 5-tuple as follows: @@ -2284,6 +2288,7 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored)) PyObject *items; PyObject *iter; PyObject *result; + defdictobject *dd = _defdictobject_CAST(op); if (dd->default_factory == NULL || dd->default_factory == Py_None) args = PyTuple_New(0); @@ -2291,7 +2296,7 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored)) args = PyTuple_Pack(1, dd->default_factory); if (args == NULL) return NULL; - items = PyObject_CallMethodNoArgs((PyObject *)dd, &_Py_ID(items)); + items = PyObject_CallMethodNoArgs(op, &_Py_ID(items)); if (items == NULL) { Py_DECREF(args); return NULL; @@ -2311,13 +2316,13 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored)) } static PyMethodDef defdict_methods[] = { - {"__missing__", (PyCFunction)defdict_missing, METH_O, + {"__missing__", defdict_missing, METH_O, defdict_missing_doc}, - {"copy", (PyCFunction)defdict_copy, METH_NOARGS, + {"copy", defdict_copy, METH_NOARGS, defdict_copy_doc}, - {"__copy__", (PyCFunction)defdict_copy, METH_NOARGS, + {"__copy__", defdict_copy, METH_NOARGS, defdict_copy_doc}, - {"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS, + {"__reduce__", defdict_reduce, METH_NOARGS, reduce_doc}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, @@ -2332,23 +2337,25 @@ static PyMemberDef defdict_members[] = { }; static void -defdict_dealloc(defdictobject *dd) +defdict_dealloc(PyObject *op) { + defdictobject *dd = _defdictobject_CAST(op); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyTypeObject *tp = Py_TYPE(dd); PyObject_GC_UnTrack(dd); Py_CLEAR(dd->default_factory); - PyDict_Type.tp_dealloc((PyObject *)dd); + PyDict_Type.tp_dealloc(op); Py_DECREF(tp); } static PyObject * -defdict_repr(defdictobject *dd) +defdict_repr(PyObject *op) { + defdictobject *dd = _defdictobject_CAST(op); PyObject *baserepr; PyObject *defrepr; PyObject *result; - baserepr = PyDict_Type.tp_repr((PyObject *)dd); + baserepr = PyDict_Type.tp_repr(op); if (baserepr == NULL) return NULL; if (dd->default_factory == NULL) @@ -2402,7 +2409,7 @@ defdict_or(PyObject* left, PyObject* right) } // Like copy(), this calls the object's class. // Override __or__/__ror__ for subclasses with different constructors. - PyObject *new = new_defdict((defdictobject*)self, left); + PyObject *new = new_defdict(self, left); if (!new) { return NULL; } @@ -2414,24 +2421,26 @@ defdict_or(PyObject* left, PyObject* right) } static int -defdict_traverse(PyObject *self, visitproc visit, void *arg) +defdict_traverse(PyObject *op, visitproc visit, void *arg) { + defdictobject *self = _defdictobject_CAST(op); Py_VISIT(Py_TYPE(self)); - Py_VISIT(((defdictobject *)self)->default_factory); - return PyDict_Type.tp_traverse(self, visit, arg); + Py_VISIT(self->default_factory); + return PyDict_Type.tp_traverse(op, visit, arg); } static int -defdict_tp_clear(defdictobject *dd) +defdict_tp_clear(PyObject *op) { + defdictobject *dd = _defdictobject_CAST(op); Py_CLEAR(dd->default_factory); - return PyDict_Type.tp_clear((PyObject *)dd); + return PyDict_Type.tp_clear(op); } static int defdict_init(PyObject *self, PyObject *args, PyObject *kwds) { - defdictobject *dd = (defdictobject *)self; + defdictobject *dd = _defdictobject_CAST(self); PyObject *olddefault = dd->default_factory; PyObject *newdefault = NULL; PyObject *newargs; From 6268c5e4dfd3a991d6807bb7b342a5a6ccc98253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 25 Jan 2025 18:09:54 +0100 Subject: [PATCH 4/8] fix UBSan failures for `tuplegetterobject` --- Modules/_collectionsmodule.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index d353b6780396b7..794b277fce239b 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2636,6 +2636,8 @@ typedef struct { PyObject* doc; } _tuplegetterobject; +#define _tuplegetterobject_CAST(op) ((_tuplegetterobject *)(op)) + /*[clinic input] @classmethod _tuplegetter.__new__ as tuplegetter_new @@ -2662,7 +2664,7 @@ tuplegetter_new_impl(PyTypeObject *type, Py_ssize_t index, PyObject *doc) static PyObject * tuplegetter_descr_get(PyObject *self, PyObject *obj, PyObject *type) { - Py_ssize_t index = ((_tuplegetterobject*)self)->index; + Py_ssize_t index = _tuplegetterobject_CAST(self)->index; PyObject *result; if (obj == NULL) { @@ -2703,7 +2705,7 @@ tuplegetter_descr_set(PyObject *self, PyObject *obj, PyObject *value) static int tuplegetter_traverse(PyObject *self, visitproc visit, void *arg) { - _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; + _tuplegetterobject *tuplegetter = _tuplegetterobject_CAST(self); Py_VISIT(Py_TYPE(tuplegetter)); Py_VISIT(tuplegetter->doc); return 0; @@ -2712,30 +2714,33 @@ tuplegetter_traverse(PyObject *self, visitproc visit, void *arg) static int tuplegetter_clear(PyObject *self) { - _tuplegetterobject *tuplegetter = (_tuplegetterobject *)self; + _tuplegetterobject *tuplegetter = _tuplegetterobject_CAST(self); Py_CLEAR(tuplegetter->doc); return 0; } static void -tuplegetter_dealloc(_tuplegetterobject *self) +tuplegetter_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - tuplegetter_clear((PyObject*)self); - tp->tp_free((PyObject*)self); + (void)tuplegetter_clear(self); + tp->tp_free(self); Py_DECREF(tp); } static PyObject* -tuplegetter_reduce(_tuplegetterobject *self, PyObject *Py_UNUSED(ignored)) +tuplegetter_reduce(PyObject *op, PyObject *Py_UNUSED(args)) { - return Py_BuildValue("(O(nO))", (PyObject*) Py_TYPE(self), self->index, self->doc); + _tuplegetterobject *self = _tuplegetterobject_CAST(op); + return Py_BuildValue("(O(nO))", (PyObject *)Py_TYPE(self), + self->index, self->doc); } static PyObject* -tuplegetter_repr(_tuplegetterobject *self) +tuplegetter_repr(PyObject *op) { + _tuplegetterobject *self = _tuplegetterobject_CAST(op); return PyUnicode_FromFormat("%s(%zd, %R)", _PyType_Name(Py_TYPE(self)), self->index, self->doc); @@ -2748,7 +2753,7 @@ static PyMemberDef tuplegetter_members[] = { }; static PyMethodDef tuplegetter_methods[] = { - {"__reduce__", (PyCFunction)tuplegetter_reduce, METH_NOARGS, NULL}, + {"__reduce__", tuplegetter_reduce, METH_NOARGS, NULL}, {NULL}, }; From 337cb29e2fb5f52e1f414ebf31d051c0e531aa6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 25 Jan 2025 18:10:05 +0100 Subject: [PATCH 5/8] suppress unused return values --- Modules/_collectionsmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 794b277fce239b..ad3204f9c49a26 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2808,7 +2808,7 @@ collections_clear(PyObject *mod) static void collections_free(void *module) { - collections_clear((PyObject *)module); + (void)collections_clear((PyObject *)module); } PyDoc_STRVAR(collections_doc, From cd3775b258bbc049b5cfcad75eaac1da0ccedb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:47:01 +0100 Subject: [PATCH 6/8] use 'dummy' for NOARGS method --- Modules/_collectionsmodule.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index ad3204f9c49a26..aa526fc15b0772 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2027,7 +2027,7 @@ dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } static PyObject * -dequeiter_len(PyObject *op, PyObject *Py_UNUSED(args)) +dequeiter_len(PyObject *op, PyObject *Py_UNUSED(dummy)) { dequeiterobject *it = _dequeiterobject_CAST(op); Py_ssize_t len = FT_ATOMIC_LOAD_SSIZE(it->counter); @@ -2037,7 +2037,7 @@ dequeiter_len(PyObject *op, PyObject *Py_UNUSED(args)) PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); static PyObject * -dequeiter_reduce(PyObject *op, PyObject *Py_UNUSED(args)) +dequeiter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { dequeiterobject *it = _dequeiterobject_CAST(op); PyTypeObject *ty = Py_TYPE(it); @@ -2250,7 +2250,7 @@ new_defdict(PyObject *op, PyObject *arg) PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); static PyObject * -defdict_copy(PyObject *op, PyObject *Py_UNUSED(args)) +defdict_copy(PyObject *op, PyObject *Py_UNUSED(dummy)) { /* This calls the object's class. That only works for subclasses whose class constructor has the same signature. Subclasses that @@ -2260,7 +2260,7 @@ defdict_copy(PyObject *op, PyObject *Py_UNUSED(args)) } static PyObject * -defdict_reduce(PyObject *op, PyObject *Py_UNUSED(args)) +defdict_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { /* __reduce__ must return a 5-tuple as follows: @@ -2730,7 +2730,7 @@ tuplegetter_dealloc(PyObject *self) } static PyObject* -tuplegetter_reduce(PyObject *op, PyObject *Py_UNUSED(args)) +tuplegetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { _tuplegetterobject *self = _tuplegetterobject_CAST(op); return Py_BuildValue("(O(nO))", (PyObject *)Py_TYPE(self), From 46da2c41d480a7dd24c5c49a9079d84ead68783c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:30:47 +0100 Subject: [PATCH 7/8] Do not add an underscore to the macro if none is needed. --- Modules/_collectionsmodule.c | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index aa526fc15b0772..229e495f598350 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -144,7 +144,7 @@ struct dequeobject { PyObject *weakreflist; }; -#define _dequeobject_CAST(op) ((dequeobject *)(op)) +#define dequeobject_CAST(op) ((dequeobject *)(op)) /* For debug builds, add error checking to track the endpoints * in the chain of links. The goal is to make sure that link @@ -574,7 +574,7 @@ deque_extendleft_impl(dequeobject *deque, PyObject *iterable) static PyObject * deque_inplace_concat(PyObject *self, PyObject *other) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); PyObject *result; // deque_extend is thread-safe @@ -693,7 +693,7 @@ deque_concat_lock_held(dequeobject *deque, PyObject *other) static PyObject * deque_concat(PyObject *self, PyObject *other) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_concat_lock_held(deque, other); @@ -711,7 +711,7 @@ deque_clear(PyObject *self) Py_ssize_t n, m; PyObject *item; PyObject **itemptr, **limit; - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); if (Py_SIZE(deque) == 0) return 0; @@ -883,7 +883,7 @@ deque_inplace_repeat_lock_held(dequeobject *deque, Py_ssize_t n) static PyObject * deque_inplace_repeat(PyObject *self, Py_ssize_t n) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_inplace_repeat_lock_held(deque, n); @@ -894,7 +894,7 @@ deque_inplace_repeat(PyObject *self, Py_ssize_t n) static PyObject * deque_repeat(PyObject *self, Py_ssize_t n) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); dequeobject *new_deque; PyObject *rv; @@ -1210,7 +1210,7 @@ deque_contains_lock_held(dequeobject *deque, PyObject *v) static int deque_contains(PyObject *self, PyObject *v) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); int result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_contains_lock_held(deque, v); @@ -1404,7 +1404,7 @@ deque_item_lock_held(dequeobject *deque, Py_ssize_t i) static PyObject * deque_item(PyObject *self, Py_ssize_t i) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_item_lock_held(deque, i); @@ -1516,7 +1516,7 @@ deque_ass_item_lock_held(dequeobject *deque, Py_ssize_t i, PyObject *v) static int deque_ass_item(PyObject *self, Py_ssize_t i, PyObject *v) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); int result; Py_BEGIN_CRITICAL_SECTION(deque); result = deque_ass_item_lock_held(deque, i, v); @@ -1527,7 +1527,7 @@ deque_ass_item(PyObject *self, Py_ssize_t i, PyObject *v) static void deque_dealloc(PyObject *self) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); PyTypeObject *tp = Py_TYPE(deque); Py_ssize_t i; @@ -1552,7 +1552,7 @@ deque_dealloc(PyObject *self) static int deque_traverse(PyObject *self, visitproc visit, void *arg) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); Py_VISIT(Py_TYPE(deque)); block *b; @@ -1631,7 +1631,7 @@ deque_repr(PyObject *deque) Py_ReprLeave(deque); return NULL; } - Py_ssize_t maxlen = _dequeobject_CAST(deque)->maxlen; + Py_ssize_t maxlen = dequeobject_CAST(deque)->maxlen; if (maxlen >= 0) result = PyUnicode_FromFormat("%s(%R, maxlen=%zd)", _PyType_Name(Py_TYPE(deque)), aslist, @@ -1786,7 +1786,7 @@ deque___sizeof___impl(dequeobject *deque) static PyObject * deque_get_maxlen(PyObject *self, void *Py_UNUSED(closure)) { - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); if (deque->maxlen < 0) Py_RETURN_NONE; return PyLong_FromSsize_t(deque->maxlen); @@ -1898,13 +1898,13 @@ typedef struct { Py_ssize_t counter; /* number of items remaining for iteration */ } dequeiterobject; -#define _dequeiterobject_CAST(op) ((dequeiterobject *)(op)) +#define dequeiterobject_CAST(op) ((dequeiterobject *)(op)) static PyObject * deque_iter(PyObject *self) { dequeiterobject *it; - dequeobject *deque = _dequeobject_CAST(self); + dequeobject *deque = dequeobject_CAST(self); collections_state *state = find_module_state_by_def(Py_TYPE(deque)); it = PyObject_GC_New(dequeiterobject, state->dequeiter_type); @@ -1924,7 +1924,7 @@ deque_iter(PyObject *self) static int dequeiter_traverse(PyObject *op, visitproc visit, void *arg) { - dequeiterobject *dio = _dequeiterobject_CAST(op); + dequeiterobject *dio = dequeiterobject_CAST(op); Py_VISIT(Py_TYPE(dio)); Py_VISIT(dio->deque); return 0; @@ -1933,7 +1933,7 @@ dequeiter_traverse(PyObject *op, visitproc visit, void *arg) static int dequeiter_clear(PyObject *op) { - dequeiterobject *dio = _dequeiterobject_CAST(op); + dequeiterobject *dio = dequeiterobject_CAST(op); Py_CLEAR(dio->deque); return 0; } @@ -1980,7 +1980,7 @@ static PyObject * dequeiter_next(PyObject *op) { PyObject *result; - dequeiterobject *it = _dequeiterobject_CAST(op); + dequeiterobject *it = dequeiterobject_CAST(op); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. dequeobject *deque = it->deque; @@ -2029,7 +2029,7 @@ dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * dequeiter_len(PyObject *op, PyObject *Py_UNUSED(dummy)) { - dequeiterobject *it = _dequeiterobject_CAST(op); + dequeiterobject *it = dequeiterobject_CAST(op); Py_ssize_t len = FT_ATOMIC_LOAD_SSIZE(it->counter); return PyLong_FromSsize_t(len); } @@ -2039,7 +2039,7 @@ PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list( static PyObject * dequeiter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { - dequeiterobject *it = _dequeiterobject_CAST(op); + dequeiterobject *it = dequeiterobject_CAST(op); PyTypeObject *ty = Py_TYPE(it); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. @@ -2131,7 +2131,7 @@ static PyObject * dequereviter_next(PyObject *self) { PyObject *item; - dequeiterobject *it = _dequeiterobject_CAST(self); + dequeiterobject *it = dequeiterobject_CAST(self); // It's safe to access it->deque without holding the per-object lock for it // here; it->deque is only assigned during construction of it. dequeobject *deque = it->deque; @@ -2203,7 +2203,7 @@ typedef struct { PyObject *default_factory; } defdictobject; -#define _defdictobject_CAST(op) ((defdictobject *)(op)) +#define defdictobject_CAST(op) ((defdictobject *)(op)) static PyType_Spec defdict_spec; @@ -2217,7 +2217,7 @@ PyDoc_STRVAR(defdict_missing_doc, static PyObject * defdict_missing(PyObject *op, PyObject *key) { - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); PyObject *factory = dd->default_factory; PyObject *value; if (factory == NULL || factory == Py_None) { @@ -2242,7 +2242,7 @@ defdict_missing(PyObject *op, PyObject *key) static inline PyObject* new_defdict(PyObject *op, PyObject *arg) { - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), dd->default_factory ? dd->default_factory : Py_None, arg, NULL); } @@ -2288,7 +2288,7 @@ defdict_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) PyObject *items; PyObject *iter; PyObject *result; - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); if (dd->default_factory == NULL || dd->default_factory == Py_None) args = PyTuple_New(0); @@ -2339,7 +2339,7 @@ static PyMemberDef defdict_members[] = { static void defdict_dealloc(PyObject *op) { - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyTypeObject *tp = Py_TYPE(dd); PyObject_GC_UnTrack(dd); @@ -2351,7 +2351,7 @@ defdict_dealloc(PyObject *op) static PyObject * defdict_repr(PyObject *op) { - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); PyObject *baserepr; PyObject *defrepr; PyObject *result; @@ -2423,7 +2423,7 @@ defdict_or(PyObject* left, PyObject* right) static int defdict_traverse(PyObject *op, visitproc visit, void *arg) { - defdictobject *self = _defdictobject_CAST(op); + defdictobject *self = defdictobject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->default_factory); return PyDict_Type.tp_traverse(op, visit, arg); @@ -2432,7 +2432,7 @@ defdict_traverse(PyObject *op, visitproc visit, void *arg) static int defdict_tp_clear(PyObject *op) { - defdictobject *dd = _defdictobject_CAST(op); + defdictobject *dd = defdictobject_CAST(op); Py_CLEAR(dd->default_factory); return PyDict_Type.tp_clear(op); } @@ -2440,7 +2440,7 @@ defdict_tp_clear(PyObject *op) static int defdict_init(PyObject *self, PyObject *args, PyObject *kwds) { - defdictobject *dd = _defdictobject_CAST(self); + defdictobject *dd = defdictobject_CAST(self); PyObject *olddefault = dd->default_factory; PyObject *newdefault = NULL; PyObject *newargs; @@ -2636,7 +2636,7 @@ typedef struct { PyObject* doc; } _tuplegetterobject; -#define _tuplegetterobject_CAST(op) ((_tuplegetterobject *)(op)) +#define tuplegetterobject_CAST(op) ((_tuplegetterobject *)(op)) /*[clinic input] @classmethod @@ -2664,7 +2664,7 @@ tuplegetter_new_impl(PyTypeObject *type, Py_ssize_t index, PyObject *doc) static PyObject * tuplegetter_descr_get(PyObject *self, PyObject *obj, PyObject *type) { - Py_ssize_t index = _tuplegetterobject_CAST(self)->index; + Py_ssize_t index = tuplegetterobject_CAST(self)->index; PyObject *result; if (obj == NULL) { @@ -2705,7 +2705,7 @@ tuplegetter_descr_set(PyObject *self, PyObject *obj, PyObject *value) static int tuplegetter_traverse(PyObject *self, visitproc visit, void *arg) { - _tuplegetterobject *tuplegetter = _tuplegetterobject_CAST(self); + _tuplegetterobject *tuplegetter = tuplegetterobject_CAST(self); Py_VISIT(Py_TYPE(tuplegetter)); Py_VISIT(tuplegetter->doc); return 0; @@ -2714,7 +2714,7 @@ tuplegetter_traverse(PyObject *self, visitproc visit, void *arg) static int tuplegetter_clear(PyObject *self) { - _tuplegetterobject *tuplegetter = _tuplegetterobject_CAST(self); + _tuplegetterobject *tuplegetter = tuplegetterobject_CAST(self); Py_CLEAR(tuplegetter->doc); return 0; } @@ -2732,7 +2732,7 @@ tuplegetter_dealloc(PyObject *self) static PyObject* tuplegetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) { - _tuplegetterobject *self = _tuplegetterobject_CAST(op); + _tuplegetterobject *self = tuplegetterobject_CAST(op); return Py_BuildValue("(O(nO))", (PyObject *)Py_TYPE(self), self->index, self->doc); } @@ -2740,7 +2740,7 @@ tuplegetter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject* tuplegetter_repr(PyObject *op) { - _tuplegetterobject *self = _tuplegetterobject_CAST(op); + _tuplegetterobject *self = tuplegetterobject_CAST(op); return PyUnicode_FromFormat("%s(%zd, %R)", _PyType_Name(Py_TYPE(self)), self->index, self->doc); From b245b6893a2a2e14c44fa3ec8797bf78e2828160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 8 Feb 2025 18:00:21 +0100 Subject: [PATCH 8/8] Remove unnecessary cast --- Modules/_collectionsmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 229e495f598350..b2173d86445cc4 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2046,7 +2046,7 @@ dequeiter_reduce(PyObject *op, PyObject *Py_UNUSED(dummy)) dequeobject *deque = it->deque; Py_ssize_t size, counter; Py_BEGIN_CRITICAL_SECTION2(it, deque); - size = Py_SIZE((PyObject *)deque); + size = Py_SIZE(deque); counter = it->counter; Py_END_CRITICAL_SECTION2(); return Py_BuildValue("O(On)", ty, deque, size - counter);