Skip to content

gh-111178: fix UBSan failures in Modules/_decimal #129074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 44 additions & 35 deletions Modules/_decimal/_decimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -1413,24 +1421,26 @@ 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);
return 0;
}

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);
Expand Down Expand Up @@ -1473,15 +1483,15 @@ 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];
char traps[MPD_MAX_SIGNAL_LIST];
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);
Expand All @@ -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
Expand Down Expand Up @@ -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}
};
Expand Down Expand Up @@ -1946,39 +1956,39 @@ 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);
return 0;
}

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;
Expand All @@ -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;
Expand All @@ -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}
};

Expand Down Expand Up @@ -5021,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}
};

Expand Down
Loading