https://github.com/python/cpython/commit/d6f010dead1a0d4b8a9e51f0187617b0394c9c2a
commit: d6f010dead1a0d4b8a9e51f0187617b0394c9c2a
branch: main
author: Bénédikt Tran <[email protected]>
committer: encukou <[email protected]>
date: 2025-01-27T15:15:42+01:00
summary:
gh-111178: fix UBSan failures in `Modules/_decimal` (GH-129074)
* Introduce & use cast macros
* fix UBSan failures for `PyDecContextObject`
* fix UBSan failures for `PyDecContextManagerObject`
* remove redundant casts for `PyDecObject`
files:
M Modules/_decimal/_decimal.c
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index b9abd8bd2e7a53..78cf6b1426493b 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,23 +197,27 @@ 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)
#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 SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags)
-#define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags)
-#define CTX(v) (&((PyDecContextObject *)v)->ctx)
-#define CtxCaps(v) (((PyDecContextObject *)v)->capitals)
+#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)
+#define CtxCaps(v) (_PyDecContextObject_CAST(v)->capitals)
static inline decimal_state *
get_module_state_from_ctx(PyObject *v)
@@ -1413,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);
@@ -1422,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);
@@ -1473,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];
@@ -1481,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);
@@ -1501,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
@@ -1621,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}
};
@@ -1946,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);
@@ -1956,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;
@@ -1989,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;
@@ -2005,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}
};
@@ -5041,8 +5050,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}
};
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]