Skip to content

Commit 7a6384e

Browse files
committed
fix UBSan failures for defdictobject
1 parent a19302d commit 7a6384e

File tree

1 file changed

+31
-22
lines changed

1 file changed

+31
-22
lines changed

Modules/_collectionsmodule.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,8 @@ typedef struct {
22032203
PyObject *default_factory;
22042204
} defdictobject;
22052205

2206+
#define _defdictobject_CAST(op) ((defdictobject *)(op))
2207+
22062208
static PyType_Spec defdict_spec;
22072209

22082210
PyDoc_STRVAR(defdict_missing_doc,
@@ -2213,8 +2215,9 @@ PyDoc_STRVAR(defdict_missing_doc,
22132215
");
22142216

22152217
static PyObject *
2216-
defdict_missing(defdictobject *dd, PyObject *key)
2218+
defdict_missing(PyObject *op, PyObject *key)
22172219
{
2220+
defdictobject *dd = _defdictobject_CAST(op);
22182221
PyObject *factory = dd->default_factory;
22192222
PyObject *value;
22202223
if (factory == NULL || factory == Py_None) {
@@ -2229,34 +2232,35 @@ defdict_missing(defdictobject *dd, PyObject *key)
22292232
value = _PyObject_CallNoArgs(factory);
22302233
if (value == NULL)
22312234
return value;
2232-
if (PyObject_SetItem((PyObject *)dd, key, value) < 0) {
2235+
if (PyObject_SetItem(op, key, value) < 0) {
22332236
Py_DECREF(value);
22342237
return NULL;
22352238
}
22362239
return value;
22372240
}
22382241

22392242
static inline PyObject*
2240-
new_defdict(defdictobject *dd, PyObject *arg)
2243+
new_defdict(PyObject *op, PyObject *arg)
22412244
{
2245+
defdictobject *dd = _defdictobject_CAST(op);
22422246
return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd),
22432247
dd->default_factory ? dd->default_factory : Py_None, arg, NULL);
22442248
}
22452249

22462250
PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D.");
22472251

22482252
static PyObject *
2249-
defdict_copy(defdictobject *dd, PyObject *Py_UNUSED(ignored))
2253+
defdict_copy(PyObject *op, PyObject *Py_UNUSED(args))
22502254
{
22512255
/* This calls the object's class. That only works for subclasses
22522256
whose class constructor has the same signature. Subclasses that
22532257
define a different constructor signature must override copy().
22542258
*/
2255-
return new_defdict(dd, (PyObject*)dd);
2259+
return new_defdict(op, op);
22562260
}
22572261

22582262
static PyObject *
2259-
defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
2263+
defdict_reduce(PyObject *op, PyObject *Py_UNUSED(args))
22602264
{
22612265
/* __reduce__ must return a 5-tuple as follows:
22622266
@@ -2284,14 +2288,15 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
22842288
PyObject *items;
22852289
PyObject *iter;
22862290
PyObject *result;
2291+
defdictobject *dd = _defdictobject_CAST(op);
22872292

22882293
if (dd->default_factory == NULL || dd->default_factory == Py_None)
22892294
args = PyTuple_New(0);
22902295
else
22912296
args = PyTuple_Pack(1, dd->default_factory);
22922297
if (args == NULL)
22932298
return NULL;
2294-
items = PyObject_CallMethodNoArgs((PyObject *)dd, &_Py_ID(items));
2299+
items = PyObject_CallMethodNoArgs(op, &_Py_ID(items));
22952300
if (items == NULL) {
22962301
Py_DECREF(args);
22972302
return NULL;
@@ -2311,13 +2316,13 @@ defdict_reduce(defdictobject *dd, PyObject *Py_UNUSED(ignored))
23112316
}
23122317

23132318
static PyMethodDef defdict_methods[] = {
2314-
{"__missing__", (PyCFunction)defdict_missing, METH_O,
2319+
{"__missing__", defdict_missing, METH_O,
23152320
defdict_missing_doc},
2316-
{"copy", (PyCFunction)defdict_copy, METH_NOARGS,
2321+
{"copy", defdict_copy, METH_NOARGS,
23172322
defdict_copy_doc},
2318-
{"__copy__", (PyCFunction)defdict_copy, METH_NOARGS,
2323+
{"__copy__", defdict_copy, METH_NOARGS,
23192324
defdict_copy_doc},
2320-
{"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS,
2325+
{"__reduce__", defdict_reduce, METH_NOARGS,
23212326
reduce_doc},
23222327
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
23232328
PyDoc_STR("See PEP 585")},
@@ -2332,23 +2337,25 @@ static PyMemberDef defdict_members[] = {
23322337
};
23332338

23342339
static void
2335-
defdict_dealloc(defdictobject *dd)
2340+
defdict_dealloc(PyObject *op)
23362341
{
2342+
defdictobject *dd = _defdictobject_CAST(op);
23372343
/* bpo-31095: UnTrack is needed before calling any callbacks */
23382344
PyTypeObject *tp = Py_TYPE(dd);
23392345
PyObject_GC_UnTrack(dd);
23402346
Py_CLEAR(dd->default_factory);
2341-
PyDict_Type.tp_dealloc((PyObject *)dd);
2347+
PyDict_Type.tp_dealloc(op);
23422348
Py_DECREF(tp);
23432349
}
23442350

23452351
static PyObject *
2346-
defdict_repr(defdictobject *dd)
2352+
defdict_repr(PyObject *op)
23472353
{
2354+
defdictobject *dd = _defdictobject_CAST(op);
23482355
PyObject *baserepr;
23492356
PyObject *defrepr;
23502357
PyObject *result;
2351-
baserepr = PyDict_Type.tp_repr((PyObject *)dd);
2358+
baserepr = PyDict_Type.tp_repr(op);
23522359
if (baserepr == NULL)
23532360
return NULL;
23542361
if (dd->default_factory == NULL)
@@ -2402,7 +2409,7 @@ defdict_or(PyObject* left, PyObject* right)
24022409
}
24032410
// Like copy(), this calls the object's class.
24042411
// Override __or__/__ror__ for subclasses with different constructors.
2405-
PyObject *new = new_defdict((defdictobject*)self, left);
2412+
PyObject *new = new_defdict(self, left);
24062413
if (!new) {
24072414
return NULL;
24082415
}
@@ -2414,24 +2421,26 @@ defdict_or(PyObject* left, PyObject* right)
24142421
}
24152422

24162423
static int
2417-
defdict_traverse(PyObject *self, visitproc visit, void *arg)
2424+
defdict_traverse(PyObject *op, visitproc visit, void *arg)
24182425
{
2426+
defdictobject *self = _defdictobject_CAST(op);
24192427
Py_VISIT(Py_TYPE(self));
2420-
Py_VISIT(((defdictobject *)self)->default_factory);
2421-
return PyDict_Type.tp_traverse(self, visit, arg);
2428+
Py_VISIT(self->default_factory);
2429+
return PyDict_Type.tp_traverse(op, visit, arg);
24222430
}
24232431

24242432
static int
2425-
defdict_tp_clear(defdictobject *dd)
2433+
defdict_tp_clear(PyObject *op)
24262434
{
2435+
defdictobject *dd = _defdictobject_CAST(op);
24272436
Py_CLEAR(dd->default_factory);
2428-
return PyDict_Type.tp_clear((PyObject *)dd);
2437+
return PyDict_Type.tp_clear(op);
24292438
}
24302439

24312440
static int
24322441
defdict_init(PyObject *self, PyObject *args, PyObject *kwds)
24332442
{
2434-
defdictobject *dd = (defdictobject *)self;
2443+
defdictobject *dd = _defdictobject_CAST(self);
24352444
PyObject *olddefault = dd->default_factory;
24362445
PyObject *newdefault = NULL;
24372446
PyObject *newargs;

0 commit comments

Comments
 (0)