From 8b55a0f47bc3464ec3283ded183a76c3b67767fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:58:33 +0100 Subject: [PATCH 1/6] Introduce cast macros --- Modules/_decimal/_decimal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 0def463c7d8b9e..949045802890ba 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -178,11 +178,15 @@ typedef struct { mpd_uint_t data[_Py_DEC_MINALLOC]; } PyDecObject; +#define _PyDecObject_CAST(op) ((PyDecObject *)(op)) + typedef struct { PyObject_HEAD uint32_t *flags; } PyDecSignalDictObject; +#define _PyDecSignalDictObject_CAST(op) ((PyDecSignalDictObject *)(op)) + typedef struct PyDecContextObject { PyObject_HEAD mpd_context_t ctx; @@ -193,12 +197,16 @@ typedef struct PyDecContextObject { decimal_state *modstate; } PyDecContextObject; +#define _PyDecContextObject_CAST(op) ((PyDecContextObject *)(op)) + typedef struct { PyObject_HEAD PyObject *local; PyObject *global; } PyDecContextManagerObject; +#define _PyDecContextManagerObject_CAST(op) ((PyDecContextManagerObject *)(op)) + #undef MPD #undef CTX #define PyDec_CheckExact(st, v) Py_IS_TYPE(v, (st)->PyDec_Type) From 1bed6f61c3ad588b4f5ebd196a83bf899d650b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:33 +0100 Subject: [PATCH 2/6] fix UBSan failures for `PyDecContextObject` --- Modules/_decimal/_decimal.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 949045802890ba..d003e83466c88b 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -216,8 +216,8 @@ typedef struct { #define MPD(v) (&((PyDecObject *)v)->dec) #define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags) #define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags) -#define CTX(v) (&((PyDecContextObject *)v)->ctx) -#define CtxCaps(v) (((PyDecContextObject *)v)->capitals) +#define CTX(v) (&_PyDecContextObject_CAST(v)->ctx) +#define CtxCaps(v) (_PyDecContextObject_CAST(v)->capitals) static inline decimal_state * get_module_state_from_ctx(PyObject *v) @@ -1421,8 +1421,9 @@ context_new(PyTypeObject *type, } static int -context_traverse(PyDecContextObject *self, visitproc visit, void *arg) +context_traverse(PyObject *op, visitproc visit, void *arg) { + PyDecContextObject *self = _PyDecContextObject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->traps); Py_VISIT(self->flags); @@ -1430,15 +1431,16 @@ context_traverse(PyDecContextObject *self, visitproc visit, void *arg) } static int -context_clear(PyDecContextObject *self) +context_clear(PyObject *op) { + PyDecContextObject *self = _PyDecContextObject_CAST(op); Py_CLEAR(self->traps); Py_CLEAR(self->flags); return 0; } static void -context_dealloc(PyDecContextObject *self) +context_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); @@ -1481,7 +1483,7 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds) } static PyObject * -context_repr(PyDecContextObject *self) +context_repr(PyObject *self) { mpd_context_t *ctx; char flags[MPD_MAX_SIGNAL_LIST]; @@ -1489,7 +1491,7 @@ context_repr(PyDecContextObject *self) int n, mem; #ifdef Py_DEBUG - decimal_state *state = get_module_state_from_ctx((PyObject *)self); + decimal_state *state = get_module_state_from_ctx(self); assert(PyDecContext_Check(state, self)); #endif ctx = CTX(self); @@ -1509,7 +1511,7 @@ context_repr(PyDecContextObject *self) "Context(prec=%zd, rounding=%s, Emin=%zd, Emax=%zd, " "capitals=%d, clamp=%d, flags=%s, traps=%s)", ctx->prec, mpd_round_string[ctx->round], ctx->emin, ctx->emax, - self->capitals, ctx->clamp, flags, traps); + CtxCaps(self), ctx->clamp, flags, traps); } static void @@ -1629,16 +1631,16 @@ context_reduce(PyObject *self, PyObject *Py_UNUSED(dummy)) static PyGetSetDef context_getsets [] = { - { "prec", (getter)context_getprec, (setter)context_setprec, NULL, NULL}, - { "Emax", (getter)context_getemax, (setter)context_setemax, NULL, NULL}, - { "Emin", (getter)context_getemin, (setter)context_setemin, NULL, NULL}, - { "rounding", (getter)context_getround, (setter)context_setround, NULL, NULL}, - { "capitals", (getter)context_getcapitals, (setter)context_setcapitals, NULL, NULL}, - { "clamp", (getter)context_getclamp, (setter)context_setclamp, NULL, NULL}, + { "prec", context_getprec, context_setprec, NULL, NULL}, + { "Emax", context_getemax, context_setemax, NULL, NULL}, + { "Emin", context_getemin, context_setemin, NULL, NULL}, + { "rounding", context_getround, context_setround, NULL, NULL}, + { "capitals", context_getcapitals, context_setcapitals, NULL, NULL}, + { "clamp", context_getclamp, context_setclamp, NULL, NULL}, #ifdef EXTRA_FUNCTIONALITY - { "_allcr", (getter)context_getallcr, (setter)context_setallcr, NULL, NULL}, - { "_traps", (getter)context_gettraps, (setter)context_settraps, NULL, NULL}, - { "_flags", (getter)context_getstatus, (setter)context_setstatus, NULL, NULL}, + { "_allcr", context_getallcr, context_setallcr, NULL, NULL}, + { "_traps", context_gettraps, context_settraps, NULL, NULL}, + { "_flags", context_getstatus, context_setstatus, NULL, NULL}, #endif {NULL} }; From f0f5b736e309cec6f1a706ecd31bceede17946b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:04:53 +0100 Subject: [PATCH 3/6] fix UBSan failures for `PyDecContextManagerObject` --- Modules/_decimal/_decimal.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index d003e83466c88b..3ebd4fa2952840 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1956,9 +1956,9 @@ ctxmanager_new(PyObject *m, PyObject *args, PyObject *kwds) } static int -ctxmanager_traverse(PyDecContextManagerObject *self, visitproc visit, - void *arg) +ctxmanager_traverse(PyObject *op, visitproc visit, void *arg) { + PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->local); Py_VISIT(self->global); @@ -1966,29 +1966,29 @@ ctxmanager_traverse(PyDecContextManagerObject *self, visitproc visit, } static int -ctxmanager_clear(PyDecContextManagerObject *self) +ctxmanager_clear(PyObject *op) { + PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op); Py_CLEAR(self->local); Py_CLEAR(self->global); return 0; } static void -ctxmanager_dealloc(PyDecContextManagerObject *self) +ctxmanager_dealloc(PyObject *self) { PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); (void)ctxmanager_clear(self); - tp->tp_free((PyObject *)self); + tp->tp_free(self); Py_DECREF(tp); } static PyObject * -ctxmanager_set_local(PyDecContextManagerObject *self, - PyObject *Py_UNUSED(dummy)) +ctxmanager_set_local(PyObject *op, PyObject *Py_UNUSED(dummy)) { PyObject *ret; - + PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op); ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->local); if (ret == NULL) { return NULL; @@ -1999,11 +1999,10 @@ ctxmanager_set_local(PyDecContextManagerObject *self, } static PyObject * -ctxmanager_restore_global(PyDecContextManagerObject *self, - PyObject *Py_UNUSED(args)) +ctxmanager_restore_global(PyObject *op, PyObject *Py_UNUSED(args)) { PyObject *ret; - + PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op); ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->global); if (ret == NULL) { return NULL; @@ -2015,8 +2014,8 @@ ctxmanager_restore_global(PyDecContextManagerObject *self, static PyMethodDef ctxmanager_methods[] = { - {"__enter__", (PyCFunction)ctxmanager_set_local, METH_NOARGS, NULL}, - {"__exit__", (PyCFunction)ctxmanager_restore_global, METH_VARARGS, NULL}, + {"__enter__", ctxmanager_set_local, METH_NOARGS, NULL}, + {"__exit__", ctxmanager_restore_global, METH_VARARGS, NULL}, {NULL, NULL} }; From 8f8ecba7bd5723b79dab9589928edbc8b3d4283c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:08:51 +0100 Subject: [PATCH 4/6] remove redundant casts for `PyDecObject` --- Modules/_decimal/_decimal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 3ebd4fa2952840..6630684146894d 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5030,8 +5030,8 @@ dec_imag(PyObject *self, void *Py_UNUSED(closure)) static PyGetSetDef dec_getsets [] = { - { "real", (getter)dec_real, NULL, NULL, NULL}, - { "imag", (getter)dec_imag, NULL, NULL, NULL}, + { "real", dec_real, NULL, NULL, NULL}, + { "imag", dec_imag, NULL, NULL, NULL}, {NULL} }; From f44421adee6be336561613e6a544479db9c8b883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:12:37 +0100 Subject: [PATCH 5/6] use macros for `PyDecSignalDictObject` --- Modules/_decimal/_decimal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 6630684146894d..37a11898b5025f 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -214,8 +214,8 @@ typedef struct { #define PyDecSignalDict_Check(st, v) Py_IS_TYPE(v, (st)->PyDecSignalDict_Type) #define PyDecContext_Check(st, v) PyObject_TypeCheck(v, (st)->PyDecContext_Type) #define MPD(v) (&((PyDecObject *)v)->dec) -#define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags) -#define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags) +#define SdFlagAddr(v) (_PyDecSignalDictObject_CAST(v)->flags) +#define SdFlags(v) (*_PyDecSignalDictObject_CAST(v)->flags) #define CTX(v) (&_PyDecContextObject_CAST(v)->ctx) #define CtxCaps(v) (_PyDecContextObject_CAST(v)->capitals) From 692cede572e58bab488183fe41d11e02c09bf4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:13:20 +0100 Subject: [PATCH 6/6] use macros for `PyDecObject` --- Modules/_decimal/_decimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 37a11898b5025f..1655600fb1d651 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -213,7 +213,7 @@ typedef struct { #define PyDec_Check(st, v) PyObject_TypeCheck(v, (st)->PyDec_Type) #define PyDecSignalDict_Check(st, v) Py_IS_TYPE(v, (st)->PyDecSignalDict_Type) #define PyDecContext_Check(st, v) PyObject_TypeCheck(v, (st)->PyDecContext_Type) -#define MPD(v) (&((PyDecObject *)v)->dec) +#define MPD(v) (&_PyDecObject_CAST(v)->dec) #define SdFlagAddr(v) (_PyDecSignalDictObject_CAST(v)->flags) #define SdFlags(v) (*_PyDecSignalDictObject_CAST(v)->flags) #define CTX(v) (&_PyDecContextObject_CAST(v)->ctx)