From 94472946551424b7dc77a5190e6d7f0a6b565020 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 16:05:02 +0100 Subject: [PATCH 01/10] fix UBSan failures for `PyThreadHandleObject` --- Modules/_threadmodule.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index dbc574f7816b85..0db786c310ba10 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -582,6 +582,8 @@ typedef struct { ThreadHandle *handle; } PyThreadHandleObject; +#define _PyThreadHandleObject_CAST(op) ((PyThreadHandleObject *)(op)) + static PyThreadHandleObject * PyThreadHandleObject_new(PyTypeObject *type) { @@ -609,8 +611,7 @@ PyThreadHandleObject_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } static int -PyThreadHandleObject_traverse(PyThreadHandleObject *self, visitproc visit, - void *arg) +PyThreadHandleObject_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); return 0; @@ -619,7 +620,7 @@ PyThreadHandleObject_traverse(PyThreadHandleObject *self, visitproc visit, static void PyThreadHandleObject_dealloc(PyObject *op) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); PyObject_GC_UnTrack(self); PyTypeObject *tp = Py_TYPE(self); ThreadHandle_decref(self->handle); @@ -630,7 +631,7 @@ PyThreadHandleObject_dealloc(PyObject *op) static PyObject * PyThreadHandleObject_repr(PyObject *op) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); PyThread_ident_t ident = ThreadHandle_ident(self->handle); return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">", Py_TYPE(self)->tp_name, ident); @@ -639,14 +640,14 @@ PyThreadHandleObject_repr(PyObject *op) static PyObject * PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(ignored)) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle)); } static PyObject * PyThreadHandleObject_join(PyObject *op, PyObject *args) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); PyObject *timeout_obj = NULL; if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) { @@ -670,7 +671,7 @@ PyThreadHandleObject_join(PyObject *op, PyObject *args) static PyObject * PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(ignored)) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) { Py_RETURN_TRUE; } @@ -682,7 +683,7 @@ PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(ignored)) static PyObject * PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(ignored)) { - PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); if (ThreadHandle_set_done(self->handle) < 0) { return NULL; } From 1083c461cb2b00e331dd20b7c721fc2858ea2150 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 16:08:07 +0100 Subject: [PATCH 02/10] use a macro for casts to `lockobject` --- Modules/_threadmodule.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 0db786c310ba10..6f2e0a3ff774ea 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -727,6 +727,8 @@ typedef struct { PyMutex lock; } lockobject; +#define _lockobject_CAST(op) ((lockobject *)(op)) + static int lock_traverse(PyObject *self, visitproc visit, void *arg) { @@ -735,13 +737,12 @@ lock_traverse(PyObject *self, visitproc visit, void *arg) } static void -lock_dealloc(PyObject *op) +lock_dealloc(PyObject *self) { - lockobject *self = (lockobject*)op; PyObject_GC_UnTrack(self); - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(self); PyTypeObject *tp = Py_TYPE(self); - tp->tp_free((PyObject*)self); + tp->tp_free(self); Py_DECREF(tp); } @@ -795,7 +796,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds, static PyObject * lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds) { - lockobject *self = (lockobject*)op; + lockobject *self = _lockobject_CAST(op); PyTime_t timeout; if (lock_acquire_parse_args(args, kwds, &timeout) < 0) { @@ -837,7 +838,7 @@ Lock the lock."); static PyObject * lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) { - lockobject *self = (lockobject*)op; + lockobject *self = _lockobject_CAST(op); /* Sanity check: the lock must be locked */ if (_PyMutex_TryUnlock(&self->lock) < 0) { PyErr_SetString(ThreadError, "release unlocked lock"); @@ -870,7 +871,7 @@ Release the lock."); static PyObject * lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) { - lockobject *self = (lockobject*)op; + lockobject *self = _lockobject_CAST(op); return PyBool_FromLong(PyMutex_IsLocked(&self->lock)); } @@ -889,7 +890,7 @@ An obsolete synonym of locked()."); static PyObject * lock_repr(PyObject *op) { - lockobject *self = (lockobject*)op; + lockobject *self = _lockobject_CAST(op); return PyUnicode_FromFormat("<%s %s object at %p>", PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self); } @@ -898,7 +899,7 @@ lock_repr(PyObject *op) static PyObject * lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args)) { - lockobject *self = (lockobject *)op; + lockobject *self = _lockobject_CAST(op); _PyMutex_at_fork_reinit(&self->lock); Py_RETURN_NONE; } From d7a39aea69ec950ade1332dd52426c43e862df3a 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 16:10:14 +0100 Subject: [PATCH 03/10] fix UBSan failures for `rlockobject` --- Modules/_threadmodule.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 6f2e0a3ff774ea..fd81894f6971e3 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -991,8 +991,10 @@ typedef struct { _PyRecursiveMutex lock; } rlockobject; +#define _rlockobject_CAST(op) ((rlockobject *)(op)) + static int -rlock_traverse(rlockobject *self, visitproc visit, void *arg) +rlock_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); return 0; @@ -1000,11 +1002,10 @@ rlock_traverse(rlockobject *self, visitproc visit, void *arg) static void -rlock_dealloc(PyObject *op) +rlock_dealloc(PyObject *self) { - rlockobject *self = (rlockobject*)op; PyObject_GC_UnTrack(self); - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(self); PyTypeObject *tp = Py_TYPE(self); tp->tp_free(self); Py_DECREF(tp); @@ -1014,7 +1015,7 @@ rlock_dealloc(PyObject *op) static PyObject * rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); PyTime_t timeout; if (lock_acquire_parse_args(args, kwds, &timeout) < 0) { @@ -1056,8 +1057,7 @@ Lock the lock."); static PyObject * rlock_release(PyObject *op, PyObject *Py_UNUSED(ignored)) { - rlockobject *self = (rlockobject*)op; - + rlockobject *self = _rlockobject_CAST(op); if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) { PyErr_SetString(PyExc_RuntimeError, "cannot release un-acquired lock"); @@ -1088,7 +1088,7 @@ Release the lock."); static PyObject * rlock_acquire_restore(PyObject *op, PyObject *args) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); PyThread_ident_t owner; Py_ssize_t count; @@ -1111,7 +1111,7 @@ For internal use by `threading.Condition`."); static PyObject * rlock_release_save(PyObject *op, PyObject *Py_UNUSED(ignored)) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); if (!_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) { PyErr_SetString(PyExc_RuntimeError, @@ -1135,7 +1135,7 @@ For internal use by `threading.Condition`."); static PyObject * rlock_recursion_count(PyObject *op, PyObject *Py_UNUSED(ignored)) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); if (_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) { return PyLong_FromSize_t(self->lock.level + 1); } @@ -1151,7 +1151,7 @@ For internal use by reentrancy checks."); static PyObject * rlock_is_owned(PyObject *op, PyObject *Py_UNUSED(ignored)) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); long owned = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock); return PyBool_FromLong(owned); } @@ -1176,7 +1176,7 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * rlock_repr(PyObject *op) { - rlockobject *self = (rlockobject*)op; + rlockobject *self = _rlockobject_CAST(op); PyThread_ident_t owner = self->lock.thread; size_t count = self->lock.level + 1; return PyUnicode_FromFormat( @@ -1189,8 +1189,9 @@ rlock_repr(PyObject *op) #ifdef HAVE_FORK static PyObject * -rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args)) +rlock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args)) { + rlockobject *self = _rlockobject_CAST(op); self->lock = (_PyRecursiveMutex){0}; Py_RETURN_NONE; } @@ -1215,7 +1216,7 @@ static PyMethodDef rlock_methods[] = { {"__exit__", rlock_release, METH_VARARGS, rlock_exit_doc}, #ifdef HAVE_FORK - {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit, + {"_at_fork_reinit", rlock__at_fork_reinit, METH_NOARGS, NULL}, #endif {NULL, NULL} /* sentinel */ From 557dbd002bd5a2fe1d27a5728291ae0e5cef0b9c 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 16:11:09 +0100 Subject: [PATCH 04/10] fix UBSan failures for `localdummyobject` --- Modules/_threadmodule.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index fd81894f6971e3..728e675dfdb1c8 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1313,14 +1313,17 @@ typedef struct { PyObject *weakreflist; /* List of weak references to self */ } localdummyobject; +#define _localdummyobject_CAST(op) ((localdummyobject *)(op)) + static void localdummy_dealloc(PyObject *op) { - localdummyobject *self = (localdummyobject*)op; - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); + localdummyobject *self = _localdummyobject_CAST(op); + if (self->weakreflist != NULL) { + PyObject_ClearWeakRefs(op); + } PyTypeObject *tp = Py_TYPE(self); - tp->tp_free((PyObject*)self); + tp->tp_free(self); Py_DECREF(tp); } From a96a296863e74c4500d19817034d8369cc6a133f 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 16:16:53 +0100 Subject: [PATCH 05/10] fix UBSan failures for `localobject` --- Modules/_threadmodule.c | 49 +++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 728e675dfdb1c8..64bbc9308eccaf 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1359,6 +1359,8 @@ typedef struct { PyObject *thread_watchdogs; } localobject; +#define _localobject_CAST(op) ((localobject *)(op)) + /* Forward declaration */ static int create_localsdict(localobject *self, thread_module_state *state, PyObject **localsdict, PyObject **sentinel_wr); @@ -1369,7 +1371,7 @@ static PyObject * create_sentinel_wr(localobject *self) { static PyMethodDef wr_callback_def = { - "clear_locals", (PyCFunction) clear_locals, METH_O + "clear_locals", clear_locals, METH_O }; PyThreadState *tstate = PyThreadState_Get(); @@ -1461,8 +1463,9 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) } static int -local_traverse(localobject *self, visitproc visit, void *arg) +local_traverse(PyObject *op, visitproc visit, void *arg) { + localobject *self = _localobject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->args); Py_VISIT(self->kw); @@ -1472,8 +1475,9 @@ local_traverse(localobject *self, visitproc visit, void *arg) } static int -local_clear(localobject *self) +local_clear(PyObject *op) { + localobject *self = _localobject_CAST(op); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->localdicts); @@ -1482,20 +1486,18 @@ local_clear(localobject *self) } static void -local_dealloc(localobject *self) +local_dealloc(PyObject *op) { + localobject *self = _localobject_CAST(op); /* Weakrefs must be invalidated right now, otherwise they can be used from code called below, which is very dangerous since Py_REFCNT(self) == 0 */ if (self->weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *) self); + PyObject_ClearWeakRefs(op); } - PyObject_GC_UnTrack(self); - - local_clear(self); - + (void)local_clear(op); PyTypeObject *tp = Py_TYPE(self); - tp->tp_free((PyObject*)self); + tp->tp_free(self); Py_DECREF(tp); } @@ -1634,8 +1636,9 @@ _ldict(localobject *self, thread_module_state *state) } static int -local_setattro(localobject *self, PyObject *name, PyObject *v) +local_setattro(PyObject *op, PyObject *name, PyObject *v) { + localobject *self = _localobject_CAST(op); PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module); assert(module != NULL); thread_module_state *state = get_thread_state(module); @@ -1656,8 +1659,7 @@ local_setattro(localobject *self, PyObject *name, PyObject *v) goto err; } - int st = - _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict); + int st = _PyObject_GenericSetAttrWithDict(op, name, v, ldict); Py_DECREF(ldict); return st; @@ -1666,7 +1668,7 @@ local_setattro(localobject *self, PyObject *name, PyObject *v) return -1; } -static PyObject *local_getattro(localobject *, PyObject *); +static PyObject *local_getattro(PyObject *, PyObject *); static PyMemberDef local_type_members[] = { {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localobject, weakreflist), Py_READONLY}, @@ -1674,12 +1676,12 @@ static PyMemberDef local_type_members[] = { }; static PyType_Slot local_type_slots[] = { - {Py_tp_dealloc, (destructor)local_dealloc}, - {Py_tp_getattro, (getattrofunc)local_getattro}, - {Py_tp_setattro, (setattrofunc)local_setattro}, + {Py_tp_dealloc, local_dealloc}, + {Py_tp_getattro, local_getattro}, + {Py_tp_setattro, local_setattro}, {Py_tp_doc, "_local()\n--\n\nThread-local data"}, - {Py_tp_traverse, (traverseproc)local_traverse}, - {Py_tp_clear, (inquiry)local_clear}, + {Py_tp_traverse, local_traverse}, + {Py_tp_clear, local_clear}, {Py_tp_new, local_new}, {Py_tp_members, local_type_members}, {0, 0} @@ -1694,8 +1696,9 @@ static PyType_Spec local_type_spec = { }; static PyObject * -local_getattro(localobject *self, PyObject *name) +local_getattro(PyObject *op, PyObject *name) { + localobject *self = _localobject_CAST(op); PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module); assert(module != NULL); thread_module_state *state = get_thread_state(module); @@ -1715,8 +1718,7 @@ local_getattro(localobject *self, PyObject *name) if (!Py_IS_TYPE(self, state->local_type)) { /* use generic lookup for subtypes */ - PyObject *res = - _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict, 0); + PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0); Py_DECREF(ldict); return res; } @@ -1730,8 +1732,7 @@ local_getattro(localobject *self, PyObject *name) } /* Fall back on generic to get __class__ and __dict__ */ - PyObject *res = - _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict, 0); + PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0); Py_DECREF(ldict); return res; } From 339a4164cf9940c01e72d0efb5996d55eb388875 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 16:17:15 +0100 Subject: [PATCH 06/10] add safe casts --- Modules/_threadmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 64bbc9308eccaf..3511f19432ad8e 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1743,7 +1743,7 @@ static PyObject * clear_locals(PyObject *locals_and_key, PyObject *dummyweakref) { PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0); - localobject *self = (localobject *)_PyWeakref_GET_REF(localweakref); + localobject *self = _localobject_CAST(_PyWeakref_GET_REF(localweakref)); if (self == NULL) { Py_RETURN_NONE; } From 17ba46108afccfd7a154fe13e74f92ed608895d6 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 16:18:50 +0100 Subject: [PATCH 07/10] cleanup module functions --- Modules/_threadmodule.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 3511f19432ad8e..ef377d8f0df972 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -2521,13 +2521,13 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj) static PyMethodDef thread_methods[] = { - {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, + {"start_new_thread", thread_PyThread_start_new_thread, METH_VARARGS, start_new_thread_doc}, - {"start_new", (PyCFunction)thread_PyThread_start_new_thread, + {"start_new", thread_PyThread_start_new_thread, METH_VARARGS, start_new_doc}, {"start_joinable_thread", _PyCFunction_CAST(thread_PyThread_start_joinable_thread), METH_VARARGS | METH_KEYWORDS, start_joinable_doc}, - {"daemon_threads_allowed", (PyCFunction)thread_daemon_threads_allowed, + {"daemon_threads_allowed", thread_daemon_threads_allowed, METH_NOARGS, daemon_threads_allowed_doc}, {"allocate_lock", thread_PyThread_allocate_lock, METH_NOARGS, allocate_lock_doc}, @@ -2537,7 +2537,7 @@ static PyMethodDef thread_methods[] = { METH_NOARGS, exit_thread_doc}, {"exit", thread_PyThread_exit_thread, METH_NOARGS, exit_doc}, - {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, + {"interrupt_main", thread_PyThread_interrupt_main, METH_VARARGS, interrupt_doc}, {"get_ident", thread_get_ident, METH_NOARGS, get_ident_doc}, @@ -2547,7 +2547,7 @@ static PyMethodDef thread_methods[] = { #endif {"_count", thread__count, METH_NOARGS, _count_doc}, - {"stack_size", (PyCFunction)thread_stack_size, + {"stack_size", thread_stack_size, METH_VARARGS, stack_size_doc}, {"_excepthook", thread_excepthook, METH_O, excepthook_doc}, @@ -2719,7 +2719,7 @@ thread_module_clear(PyObject *module) static void thread_module_free(void *module) { - thread_module_clear((PyObject *)module); + (void)thread_module_clear((PyObject *)module); } From 4b3e706dc0cff7f4d1597986898183a5741f8cad 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 18:04:42 +0100 Subject: [PATCH 08/10] use semantically correct parameter names --- Modules/_threadmodule.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index ef377d8f0df972..e45789435576ba 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -638,7 +638,7 @@ PyThreadHandleObject_repr(PyObject *op) } static PyObject * -PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(ignored)) +PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(closure)) { PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle)); @@ -669,7 +669,7 @@ PyThreadHandleObject_join(PyObject *op, PyObject *args) } static PyObject * -PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(ignored)) +PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) { @@ -681,7 +681,7 @@ PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(ignored)) } static PyObject * -PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(ignored)) +PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); if (ThreadHandle_set_done(self->handle) < 0) { @@ -836,7 +836,7 @@ PyDoc_STRVAR(enter_doc, Lock the lock."); static PyObject * -lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) +lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(dummy)) { lockobject *self = _lockobject_CAST(op); /* Sanity check: the lock must be locked */ @@ -869,7 +869,7 @@ PyDoc_STRVAR(lock_exit_doc, Release the lock."); static PyObject * -lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) +lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(dummy)) { lockobject *self = _lockobject_CAST(op); return PyBool_FromLong(PyMutex_IsLocked(&self->lock)); @@ -897,7 +897,7 @@ lock_repr(PyObject *op) #ifdef HAVE_FORK static PyObject * -lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args)) +lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(dummy)) { lockobject *self = _lockobject_CAST(op); _PyMutex_at_fork_reinit(&self->lock); @@ -1055,7 +1055,7 @@ PyDoc_STRVAR(rlock_enter_doc, Lock the lock."); static PyObject * -rlock_release(PyObject *op, PyObject *Py_UNUSED(ignored)) +rlock_release(PyObject *op, PyObject *Py_UNUSED(dummy)) { rlockobject *self = _rlockobject_CAST(op); if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) { @@ -1109,7 +1109,7 @@ PyDoc_STRVAR(rlock_acquire_restore_doc, For internal use by `threading.Condition`."); static PyObject * -rlock_release_save(PyObject *op, PyObject *Py_UNUSED(ignored)) +rlock_release_save(PyObject *op, PyObject *Py_UNUSED(dummy)) { rlockobject *self = _rlockobject_CAST(op); @@ -1133,7 +1133,7 @@ PyDoc_STRVAR(rlock_release_save_doc, For internal use by `threading.Condition`."); static PyObject * -rlock_recursion_count(PyObject *op, PyObject *Py_UNUSED(ignored)) +rlock_recursion_count(PyObject *op, PyObject *Py_UNUSED(dummy)) { rlockobject *self = _rlockobject_CAST(op); if (_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) { @@ -1149,7 +1149,7 @@ PyDoc_STRVAR(rlock_recursion_count_doc, For internal use by reentrancy checks."); static PyObject * -rlock_is_owned(PyObject *op, PyObject *Py_UNUSED(ignored)) +rlock_is_owned(PyObject *op, PyObject *Py_UNUSED(dummy)) { rlockobject *self = _rlockobject_CAST(op); long owned = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock); @@ -1189,7 +1189,7 @@ rlock_repr(PyObject *op) #ifdef HAVE_FORK static PyObject * -rlock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args)) +rlock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(dummy)) { rlockobject *self = _rlockobject_CAST(op); self->lock = (_PyRecursiveMutex){0}; From 7a5ed410e0c27c3868d550f7662fa0d2c03cb3a0 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:18:03 +0100 Subject: [PATCH 09/10] Do Do not use `_` + capital letter in new code as it is also UB. --- Modules/_threadmodule.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 1b32277ebf09ad..bd16cccdc7d622 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -582,7 +582,7 @@ typedef struct { ThreadHandle *handle; } PyThreadHandleObject; -#define _PyThreadHandleObject_CAST(op) ((PyThreadHandleObject *)(op)) +#define PyThreadHandleObject_CAST(op) ((PyThreadHandleObject *)(op)) static PyThreadHandleObject * PyThreadHandleObject_new(PyTypeObject *type) @@ -620,7 +620,7 @@ PyThreadHandleObject_traverse(PyObject *self, visitproc visit, void *arg) static void PyThreadHandleObject_dealloc(PyObject *op) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); PyObject_GC_UnTrack(self); PyTypeObject *tp = Py_TYPE(self); ThreadHandle_decref(self->handle); @@ -631,7 +631,7 @@ PyThreadHandleObject_dealloc(PyObject *op) static PyObject * PyThreadHandleObject_repr(PyObject *op) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); PyThread_ident_t ident = ThreadHandle_ident(self->handle); return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">", Py_TYPE(self)->tp_name, ident); @@ -640,14 +640,14 @@ PyThreadHandleObject_repr(PyObject *op) static PyObject * PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(closure)) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle)); } static PyObject * PyThreadHandleObject_join(PyObject *op, PyObject *args) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); PyObject *timeout_obj = NULL; if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) { @@ -671,7 +671,7 @@ PyThreadHandleObject_join(PyObject *op, PyObject *args) static PyObject * PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) { Py_RETURN_TRUE; } @@ -683,7 +683,7 @@ PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy)) static PyObject * PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(dummy)) { - PyThreadHandleObject *self = _PyThreadHandleObject_CAST(op); + PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); if (ThreadHandle_set_done(self->handle) < 0) { return NULL; } From ce0eb112f17d5678ca1e5a8347a6b3696fb94e43 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:18:39 +0100 Subject: [PATCH 10/10] Do not add an underscore to the macro if none is needed. --- Modules/_threadmodule.c | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index bd16cccdc7d622..eb06d711057ea0 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -727,7 +727,7 @@ typedef struct { PyMutex lock; } lockobject; -#define _lockobject_CAST(op) ((lockobject *)(op)) +#define lockobject_CAST(op) ((lockobject *)(op)) static int lock_traverse(PyObject *self, visitproc visit, void *arg) @@ -796,7 +796,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds, static PyObject * lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds) { - lockobject *self = _lockobject_CAST(op); + lockobject *self = lockobject_CAST(op); PyTime_t timeout; if (lock_acquire_parse_args(args, kwds, &timeout) < 0) { @@ -838,7 +838,7 @@ Lock the lock."); static PyObject * lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(dummy)) { - lockobject *self = _lockobject_CAST(op); + lockobject *self = lockobject_CAST(op); /* Sanity check: the lock must be locked */ if (_PyMutex_TryUnlock(&self->lock) < 0) { PyErr_SetString(ThreadError, "release unlocked lock"); @@ -871,7 +871,7 @@ Release the lock."); static PyObject * lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(dummy)) { - lockobject *self = _lockobject_CAST(op); + lockobject *self = lockobject_CAST(op); return PyBool_FromLong(PyMutex_IsLocked(&self->lock)); } @@ -890,7 +890,7 @@ An obsolete synonym of locked()."); static PyObject * lock_repr(PyObject *op) { - lockobject *self = _lockobject_CAST(op); + lockobject *self = lockobject_CAST(op); return PyUnicode_FromFormat("<%s %s object at %p>", PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self); } @@ -899,7 +899,7 @@ lock_repr(PyObject *op) static PyObject * lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(dummy)) { - lockobject *self = _lockobject_CAST(op); + lockobject *self = lockobject_CAST(op); _PyMutex_at_fork_reinit(&self->lock); Py_RETURN_NONE; } @@ -991,7 +991,7 @@ typedef struct { _PyRecursiveMutex lock; } rlockobject; -#define _rlockobject_CAST(op) ((rlockobject *)(op)) +#define rlockobject_CAST(op) ((rlockobject *)(op)) static int rlock_traverse(PyObject *self, visitproc visit, void *arg) @@ -1015,7 +1015,7 @@ rlock_dealloc(PyObject *self) static PyObject * rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); PyTime_t timeout; if (lock_acquire_parse_args(args, kwds, &timeout) < 0) { @@ -1057,7 +1057,7 @@ Lock the lock."); static PyObject * rlock_release(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) { PyErr_SetString(PyExc_RuntimeError, "cannot release un-acquired lock"); @@ -1088,7 +1088,7 @@ Release the lock."); static PyObject * rlock_acquire_restore(PyObject *op, PyObject *args) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); PyThread_ident_t owner; Py_ssize_t count; @@ -1111,7 +1111,7 @@ For internal use by `threading.Condition`."); static PyObject * rlock_release_save(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); if (!_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) { PyErr_SetString(PyExc_RuntimeError, @@ -1135,7 +1135,7 @@ For internal use by `threading.Condition`."); static PyObject * rlock_recursion_count(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); if (_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) { return PyLong_FromSize_t(self->lock.level + 1); } @@ -1151,7 +1151,7 @@ For internal use by reentrancy checks."); static PyObject * rlock_is_owned(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); long owned = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock); return PyBool_FromLong(owned); } @@ -1176,7 +1176,7 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * rlock_repr(PyObject *op) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); PyThread_ident_t owner = self->lock.thread; size_t count = self->lock.level + 1; return PyUnicode_FromFormat( @@ -1191,7 +1191,7 @@ rlock_repr(PyObject *op) static PyObject * rlock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(dummy)) { - rlockobject *self = _rlockobject_CAST(op); + rlockobject *self = rlockobject_CAST(op); self->lock = (_PyRecursiveMutex){0}; Py_RETURN_NONE; } @@ -1313,12 +1313,12 @@ typedef struct { PyObject *weakreflist; /* List of weak references to self */ } localdummyobject; -#define _localdummyobject_CAST(op) ((localdummyobject *)(op)) +#define localdummyobject_CAST(op) ((localdummyobject *)(op)) static void localdummy_dealloc(PyObject *op) { - localdummyobject *self = _localdummyobject_CAST(op); + localdummyobject *self = localdummyobject_CAST(op); if (self->weakreflist != NULL) { PyObject_ClearWeakRefs(op); } @@ -1359,7 +1359,7 @@ typedef struct { PyObject *thread_watchdogs; } localobject; -#define _localobject_CAST(op) ((localobject *)(op)) +#define localobject_CAST(op) ((localobject *)(op)) /* Forward declaration */ static int create_localsdict(localobject *self, thread_module_state *state, @@ -1465,7 +1465,7 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) static int local_traverse(PyObject *op, visitproc visit, void *arg) { - localobject *self = _localobject_CAST(op); + localobject *self = localobject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->args); Py_VISIT(self->kw); @@ -1477,7 +1477,7 @@ local_traverse(PyObject *op, visitproc visit, void *arg) static int local_clear(PyObject *op) { - localobject *self = _localobject_CAST(op); + localobject *self = localobject_CAST(op); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->localdicts); @@ -1488,7 +1488,7 @@ local_clear(PyObject *op) static void local_dealloc(PyObject *op) { - localobject *self = _localobject_CAST(op); + localobject *self = localobject_CAST(op); /* Weakrefs must be invalidated right now, otherwise they can be used from code called below, which is very dangerous since Py_REFCNT(self) == 0 */ if (self->weakreflist != NULL) { @@ -1646,7 +1646,7 @@ _ldict(localobject *self, thread_module_state *state) static int local_setattro(PyObject *op, PyObject *name, PyObject *v) { - localobject *self = _localobject_CAST(op); + localobject *self = localobject_CAST(op); PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module); assert(module != NULL); thread_module_state *state = get_thread_state(module); @@ -1706,7 +1706,7 @@ static PyType_Spec local_type_spec = { static PyObject * local_getattro(PyObject *op, PyObject *name) { - localobject *self = _localobject_CAST(op); + localobject *self = localobject_CAST(op); PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module); assert(module != NULL); thread_module_state *state = get_thread_state(module); @@ -1751,7 +1751,7 @@ static PyObject * clear_locals(PyObject *locals_and_key, PyObject *dummyweakref) { PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0); - localobject *self = _localobject_CAST(_PyWeakref_GET_REF(localweakref)); + localobject *self = localobject_CAST(_PyWeakref_GET_REF(localweakref)); if (self == NULL) { Py_RETURN_NONE; }