https://github.com/python/cpython/commit/73bbaf33ae1018f2f90480c4185717f3a49bf857 commit: 73bbaf33ae1018f2f90480c4185717f3a49bf857 branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: encukou <encu...@gmail.com> date: 2025-02-24T13:38:18+01:00 summary:
gh-111178: fix UBSan failures in `Modules/selectmodule.c` (GH-129792) Fix some UBSan failures for `pollObject`, `devpollObject`, `pyEpoll_Object` as well as for `kqueue_event_Object`, `kqueue_queue_Object` and `kqueue_tracking_after_fork`. Suppress unused return values. Rename the unused parameter in `METH_NOARGS` and getter/setter methods to `dummy` and `closure` respectively for semantic purposes. Explicitly declare `_select_exec` as a `static` function. files: M Modules/selectmodule.c diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index c75e2ba28c5b4e..d701026b50887c 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -439,6 +439,8 @@ typedef struct { int poll_running; } pollObject; +#define pollObject_CAST(op) ((pollObject *)(op)) + /* Update the malloc'ed array of pollfds to match the dictionary contained within a pollObject. Return 1 on success, 0 on an error. */ @@ -772,11 +774,13 @@ newPollObject(PyObject *module) } static void -poll_dealloc(pollObject *self) +poll_dealloc(PyObject *op) { - PyObject* type = (PyObject *)Py_TYPE(self); - if (self->ufds != NULL) + pollObject *self = pollObject_CAST(op); + PyTypeObject *type = Py_TYPE(self); + if (self->ufds != NULL) { PyMem_Free(self->ufds); + } Py_XDECREF(self->dict); PyObject_Free(self); Py_DECREF(type); @@ -794,6 +798,8 @@ typedef struct { struct pollfd *fds; } devpollObject; +#define devpollObject_CAST(op) ((devpollObject *)(op)) + static PyObject * devpoll_err_closed(void) { @@ -1086,13 +1092,14 @@ select_devpoll_close_impl(devpollObject *self) Py_RETURN_NONE; } -static PyObject* -devpoll_get_closed(devpollObject *self, void *Py_UNUSED(ignored)) +static PyObject * +devpoll_get_closed(PyObject *op, void *Py_UNUSED(closure)) { - if (self->fd_devpoll < 0) + devpollObject *self = devpollObject_CAST(op); + if (self->fd_devpoll < 0) { Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + } + Py_RETURN_FALSE; } /*[clinic input] @@ -1112,7 +1119,7 @@ select_devpoll_fileno_impl(devpollObject *self) } static PyGetSetDef devpoll_getsetlist[] = { - {"closed", (getter)devpoll_get_closed, NULL, + {"closed", devpoll_get_closed, NULL, "True if the devpoll object is closed"}, {0}, }; @@ -1163,9 +1170,10 @@ newDevPollObject(PyObject *module) } static void -devpoll_dealloc(devpollObject *self) +devpoll_dealloc(PyObject *op) { - PyObject *type = (PyObject *)Py_TYPE(self); + devpollObject *self = devpollObject_CAST(op); + PyTypeObject *type = Py_TYPE(self); (void)devpoll_internal_close(self); PyMem_Free(self->fds); PyObject_Free(self); @@ -1275,6 +1283,8 @@ typedef struct { SOCKET epfd; /* epoll control file descriptor */ } pyEpoll_Object; +#define pyEpoll_Object_CAST(op) ((pyEpoll_Object *)(op)) + static PyObject * pyepoll_err_closed(void) { @@ -1377,13 +1387,14 @@ select_epoll_impl(PyTypeObject *type, int sizehint, int flags) static void -pyepoll_dealloc(pyEpoll_Object *self) +pyepoll_dealloc(PyObject *op) { - PyTypeObject* type = Py_TYPE(self); + pyEpoll_Object *self = pyEpoll_Object_CAST(op); + PyTypeObject *type = Py_TYPE(self); (void)pyepoll_internal_close(self); freefunc epoll_free = PyType_GetSlot(type, Py_tp_free); - epoll_free((PyObject *)self); - Py_DECREF((PyObject *)type); + epoll_free(self); + Py_DECREF(type); } /*[clinic input] @@ -1408,13 +1419,14 @@ select_epoll_close_impl(pyEpoll_Object *self) } -static PyObject* -pyepoll_get_closed(pyEpoll_Object *self, void *Py_UNUSED(ignored)) +static PyObject * +pyepoll_get_closed(PyObject *op, void *Py_UNUSED(closure)) { - if (self->epfd < 0) + pyEpoll_Object *self = pyEpoll_Object_CAST(op); + if (self->epfd < 0) { Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + } + Py_RETURN_FALSE; } /*[clinic input] @@ -1707,7 +1719,7 @@ select_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type, } static PyGetSetDef pyepoll_getsetlist[] = { - {"closed", (getter)pyepoll_get_closed, NULL, + {"closed", pyepoll_get_closed, NULL, "True if the epoll handler is closed"}, {0}, }; @@ -1777,13 +1789,16 @@ typedef struct { struct kevent e; } kqueue_event_Object; -#define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type)) +#define kqueue_event_Object_CAST(op) ((kqueue_event_Object *)(op)) +#define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type)) typedef struct kqueue_queue_Object { PyObject_HEAD SOCKET kqfd; /* kqueue control fd */ } kqueue_queue_Object; +#define kqueue_queue_Object_CAST(op) ((kqueue_queue_Object *)(op)) + #if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P) # error uintptr_t does not match void *! #elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG) @@ -1876,9 +1891,9 @@ static struct PyMemberDef kqueue_event_members[] = { #undef KQ_OFF static PyObject * - -kqueue_event_repr(kqueue_event_Object *s) +kqueue_event_repr(PyObject *op) { + kqueue_event_Object *s = kqueue_event_Object_CAST(op); return PyUnicode_FromFormat( "<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x " "data=0x%llx udata=%p>", @@ -1887,7 +1902,7 @@ kqueue_event_repr(kqueue_event_Object *s) } static int -kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) +kqueue_event_init(PyObject *op, PyObject *args, PyObject *kwds) { PyObject *pfd; static char *kwlist[] = {"ident", "filter", "flags", "fflags", @@ -1896,11 +1911,14 @@ kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) FILTER_FMT_UNIT FLAGS_FMT_UNIT FFLAGS_FMT_UNIT DATA_FMT_UNIT UINTPTRT_FMT_UNIT ":kevent"; + kqueue_event_Object *self = kqueue_event_Object_CAST(op); EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */ if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist, - &pfd, &(self->e.filter), &(self->e.flags), - &(self->e.fflags), &(self->e.data), &(self->e.udata))) { + &pfd, &(self->e.filter), + &(self->e.flags), &(self->e.fflags), + &(self->e.data), &(self->e.udata))) + { return -1; } @@ -1917,15 +1935,16 @@ kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) } static PyObject * -kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, - int op) +kqueue_event_richcompare(PyObject *lhs, PyObject *rhs, int op) { int result; + kqueue_event_Object *s = kqueue_event_Object_CAST(lhs); _selectstate *state = _selectstate_by_type(Py_TYPE(s)); - if (!kqueue_event_Check(o, state)) { + if (!kqueue_event_Check(rhs, state)) { Py_RETURN_NOTIMPLEMENTED; } + kqueue_event_Object *o = (kqueue_event_Object *)rhs; // fast cast #define CMP(a, b) ((a) != (b)) ? ((a) < (b) ? -1 : 1) result = CMP(s->e.ident, o->e.ident) @@ -1965,8 +1984,8 @@ kqueue_queue_err_closed(void) return NULL; } -static PyObject* -kqueue_tracking_after_fork(PyObject *module) { +static PyObject * +kqueue_tracking_after_fork(PyObject *module, PyObject *Py_UNUSED(dummy)) { _selectstate *state = get_select_state(module); _kqueue_list_item *item = state->kqueue_open_list; state->kqueue_open_list = NULL; @@ -1984,7 +2003,7 @@ kqueue_tracking_after_fork(PyObject *module) { } static PyMethodDef kqueue_tracking_after_fork_def = { - "kqueue_tracking_after_fork", (PyCFunction)kqueue_tracking_after_fork, + "kqueue_tracking_after_fork", kqueue_tracking_after_fork, METH_NOARGS, "Invalidate open select.kqueue objects after fork." }; @@ -2173,10 +2192,11 @@ select_kqueue_impl(PyTypeObject *type) } static void -kqueue_queue_finalize(kqueue_queue_Object *self) +kqueue_queue_finalize(PyObject *op) { - PyObject* error = PyErr_GetRaisedException(); - kqueue_queue_internal_close(self); + kqueue_queue_Object *self = kqueue_queue_Object_CAST(op); + PyObject *error = PyErr_GetRaisedException(); + (void)kqueue_queue_internal_close(self); PyErr_SetRaisedException(error); } @@ -2201,13 +2221,14 @@ select_kqueue_close_impl(kqueue_queue_Object *self) Py_RETURN_NONE; } -static PyObject* -kqueue_queue_get_closed(kqueue_queue_Object *self, void *Py_UNUSED(ignored)) +static PyObject * +kqueue_queue_get_closed(PyObject *op, void *Py_UNUSED(closure)) { - if (self->kqfd < 0) + kqueue_queue_Object *self = kqueue_queue_Object_CAST(op); + if (self->kqfd < 0) { Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + } + Py_RETURN_FALSE; } /*[clinic input] @@ -2414,7 +2435,7 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, } static PyGetSetDef kqueue_queue_getsetlist[] = { - {"closed", (getter)kqueue_queue_get_closed, NULL, + {"closed", kqueue_queue_get_closed, NULL, "True if the kqueue handler is closed"}, {0}, }; @@ -2588,10 +2609,10 @@ _select_clear(PyObject *module) static void _select_free(void *module) { - _select_clear((PyObject *)module); + (void)_select_clear((PyObject *)module); } -int +static int _select_exec(PyObject *m) { _selectstate *state = get_select_state(m); _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com