Skip to content

Commit d6f010d

Browse files
authored
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`
1 parent ced296d commit d6f010d

File tree

1 file changed

+44
-35
lines changed

1 file changed

+44
-35
lines changed

Modules/_decimal/_decimal.c

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,15 @@ typedef struct {
178178
mpd_uint_t data[_Py_DEC_MINALLOC];
179179
} PyDecObject;
180180

181+
#define _PyDecObject_CAST(op) ((PyDecObject *)(op))
182+
181183
typedef struct {
182184
PyObject_HEAD
183185
uint32_t *flags;
184186
} PyDecSignalDictObject;
185187

188+
#define _PyDecSignalDictObject_CAST(op) ((PyDecSignalDictObject *)(op))
189+
186190
typedef struct PyDecContextObject {
187191
PyObject_HEAD
188192
mpd_context_t ctx;
@@ -193,23 +197,27 @@ typedef struct PyDecContextObject {
193197
decimal_state *modstate;
194198
} PyDecContextObject;
195199

200+
#define _PyDecContextObject_CAST(op) ((PyDecContextObject *)(op))
201+
196202
typedef struct {
197203
PyObject_HEAD
198204
PyObject *local;
199205
PyObject *global;
200206
} PyDecContextManagerObject;
201207

208+
#define _PyDecContextManagerObject_CAST(op) ((PyDecContextManagerObject *)(op))
209+
202210
#undef MPD
203211
#undef CTX
204212
#define PyDec_CheckExact(st, v) Py_IS_TYPE(v, (st)->PyDec_Type)
205213
#define PyDec_Check(st, v) PyObject_TypeCheck(v, (st)->PyDec_Type)
206214
#define PyDecSignalDict_Check(st, v) Py_IS_TYPE(v, (st)->PyDecSignalDict_Type)
207215
#define PyDecContext_Check(st, v) PyObject_TypeCheck(v, (st)->PyDecContext_Type)
208-
#define MPD(v) (&((PyDecObject *)v)->dec)
209-
#define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags)
210-
#define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags)
211-
#define CTX(v) (&((PyDecContextObject *)v)->ctx)
212-
#define CtxCaps(v) (((PyDecContextObject *)v)->capitals)
216+
#define MPD(v) (&_PyDecObject_CAST(v)->dec)
217+
#define SdFlagAddr(v) (_PyDecSignalDictObject_CAST(v)->flags)
218+
#define SdFlags(v) (*_PyDecSignalDictObject_CAST(v)->flags)
219+
#define CTX(v) (&_PyDecContextObject_CAST(v)->ctx)
220+
#define CtxCaps(v) (_PyDecContextObject_CAST(v)->capitals)
213221

214222
static inline decimal_state *
215223
get_module_state_from_ctx(PyObject *v)
@@ -1413,24 +1421,26 @@ context_new(PyTypeObject *type,
14131421
}
14141422

14151423
static int
1416-
context_traverse(PyDecContextObject *self, visitproc visit, void *arg)
1424+
context_traverse(PyObject *op, visitproc visit, void *arg)
14171425
{
1426+
PyDecContextObject *self = _PyDecContextObject_CAST(op);
14181427
Py_VISIT(Py_TYPE(self));
14191428
Py_VISIT(self->traps);
14201429
Py_VISIT(self->flags);
14211430
return 0;
14221431
}
14231432

14241433
static int
1425-
context_clear(PyDecContextObject *self)
1434+
context_clear(PyObject *op)
14261435
{
1436+
PyDecContextObject *self = _PyDecContextObject_CAST(op);
14271437
Py_CLEAR(self->traps);
14281438
Py_CLEAR(self->flags);
14291439
return 0;
14301440
}
14311441

14321442
static void
1433-
context_dealloc(PyDecContextObject *self)
1443+
context_dealloc(PyObject *self)
14341444
{
14351445
PyTypeObject *tp = Py_TYPE(self);
14361446
PyObject_GC_UnTrack(self);
@@ -1473,15 +1483,15 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds)
14731483
}
14741484

14751485
static PyObject *
1476-
context_repr(PyDecContextObject *self)
1486+
context_repr(PyObject *self)
14771487
{
14781488
mpd_context_t *ctx;
14791489
char flags[MPD_MAX_SIGNAL_LIST];
14801490
char traps[MPD_MAX_SIGNAL_LIST];
14811491
int n, mem;
14821492

14831493
#ifdef Py_DEBUG
1484-
decimal_state *state = get_module_state_from_ctx((PyObject *)self);
1494+
decimal_state *state = get_module_state_from_ctx(self);
14851495
assert(PyDecContext_Check(state, self));
14861496
#endif
14871497
ctx = CTX(self);
@@ -1501,7 +1511,7 @@ context_repr(PyDecContextObject *self)
15011511
"Context(prec=%zd, rounding=%s, Emin=%zd, Emax=%zd, "
15021512
"capitals=%d, clamp=%d, flags=%s, traps=%s)",
15031513
ctx->prec, mpd_round_string[ctx->round], ctx->emin, ctx->emax,
1504-
self->capitals, ctx->clamp, flags, traps);
1514+
CtxCaps(self), ctx->clamp, flags, traps);
15051515
}
15061516

15071517
static void
@@ -1621,16 +1631,16 @@ context_reduce(PyObject *self, PyObject *Py_UNUSED(dummy))
16211631

16221632
static PyGetSetDef context_getsets [] =
16231633
{
1624-
{ "prec", (getter)context_getprec, (setter)context_setprec, NULL, NULL},
1625-
{ "Emax", (getter)context_getemax, (setter)context_setemax, NULL, NULL},
1626-
{ "Emin", (getter)context_getemin, (setter)context_setemin, NULL, NULL},
1627-
{ "rounding", (getter)context_getround, (setter)context_setround, NULL, NULL},
1628-
{ "capitals", (getter)context_getcapitals, (setter)context_setcapitals, NULL, NULL},
1629-
{ "clamp", (getter)context_getclamp, (setter)context_setclamp, NULL, NULL},
1634+
{ "prec", context_getprec, context_setprec, NULL, NULL},
1635+
{ "Emax", context_getemax, context_setemax, NULL, NULL},
1636+
{ "Emin", context_getemin, context_setemin, NULL, NULL},
1637+
{ "rounding", context_getround, context_setround, NULL, NULL},
1638+
{ "capitals", context_getcapitals, context_setcapitals, NULL, NULL},
1639+
{ "clamp", context_getclamp, context_setclamp, NULL, NULL},
16301640
#ifdef EXTRA_FUNCTIONALITY
1631-
{ "_allcr", (getter)context_getallcr, (setter)context_setallcr, NULL, NULL},
1632-
{ "_traps", (getter)context_gettraps, (setter)context_settraps, NULL, NULL},
1633-
{ "_flags", (getter)context_getstatus, (setter)context_setstatus, NULL, NULL},
1641+
{ "_allcr", context_getallcr, context_setallcr, NULL, NULL},
1642+
{ "_traps", context_gettraps, context_settraps, NULL, NULL},
1643+
{ "_flags", context_getstatus, context_setstatus, NULL, NULL},
16341644
#endif
16351645
{NULL}
16361646
};
@@ -1946,39 +1956,39 @@ ctxmanager_new(PyObject *m, PyObject *args, PyObject *kwds)
19461956
}
19471957

19481958
static int
1949-
ctxmanager_traverse(PyDecContextManagerObject *self, visitproc visit,
1950-
void *arg)
1959+
ctxmanager_traverse(PyObject *op, visitproc visit, void *arg)
19511960
{
1961+
PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op);
19521962
Py_VISIT(Py_TYPE(self));
19531963
Py_VISIT(self->local);
19541964
Py_VISIT(self->global);
19551965
return 0;
19561966
}
19571967

19581968
static int
1959-
ctxmanager_clear(PyDecContextManagerObject *self)
1969+
ctxmanager_clear(PyObject *op)
19601970
{
1971+
PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op);
19611972
Py_CLEAR(self->local);
19621973
Py_CLEAR(self->global);
19631974
return 0;
19641975
}
19651976

19661977
static void
1967-
ctxmanager_dealloc(PyDecContextManagerObject *self)
1978+
ctxmanager_dealloc(PyObject *self)
19681979
{
19691980
PyTypeObject *tp = Py_TYPE(self);
19701981
PyObject_GC_UnTrack(self);
19711982
(void)ctxmanager_clear(self);
1972-
tp->tp_free((PyObject *)self);
1983+
tp->tp_free(self);
19731984
Py_DECREF(tp);
19741985
}
19751986

19761987
static PyObject *
1977-
ctxmanager_set_local(PyDecContextManagerObject *self,
1978-
PyObject *Py_UNUSED(dummy))
1988+
ctxmanager_set_local(PyObject *op, PyObject *Py_UNUSED(dummy))
19791989
{
19801990
PyObject *ret;
1981-
1991+
PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op);
19821992
ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->local);
19831993
if (ret == NULL) {
19841994
return NULL;
@@ -1989,11 +1999,10 @@ ctxmanager_set_local(PyDecContextManagerObject *self,
19891999
}
19902000

19912001
static PyObject *
1992-
ctxmanager_restore_global(PyDecContextManagerObject *self,
1993-
PyObject *Py_UNUSED(args))
2002+
ctxmanager_restore_global(PyObject *op, PyObject *Py_UNUSED(args))
19942003
{
19952004
PyObject *ret;
1996-
2005+
PyDecContextManagerObject *self = _PyDecContextManagerObject_CAST(op);
19972006
ret = PyDec_SetCurrentContext(PyType_GetModule(Py_TYPE(self)), self->global);
19982007
if (ret == NULL) {
19992008
return NULL;
@@ -2005,8 +2014,8 @@ ctxmanager_restore_global(PyDecContextManagerObject *self,
20052014

20062015

20072016
static PyMethodDef ctxmanager_methods[] = {
2008-
{"__enter__", (PyCFunction)ctxmanager_set_local, METH_NOARGS, NULL},
2009-
{"__exit__", (PyCFunction)ctxmanager_restore_global, METH_VARARGS, NULL},
2017+
{"__enter__", ctxmanager_set_local, METH_NOARGS, NULL},
2018+
{"__exit__", ctxmanager_restore_global, METH_VARARGS, NULL},
20102019
{NULL, NULL}
20112020
};
20122021

@@ -5041,8 +5050,8 @@ dec_imag(PyObject *self, void *Py_UNUSED(closure))
50415050

50425051
static PyGetSetDef dec_getsets [] =
50435052
{
5044-
{ "real", (getter)dec_real, NULL, NULL, NULL},
5045-
{ "imag", (getter)dec_imag, NULL, NULL, NULL},
5053+
{ "real", dec_real, NULL, NULL, NULL},
5054+
{ "imag", dec_imag, NULL, NULL, NULL},
50465055
{NULL}
50475056
};
50485057

0 commit comments

Comments
 (0)