summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorEddie Elizondo <eelizondo@fb.com>2019-09-19 16:29:05 (GMT)
committerDino Viehland <dinoviehland@gmail.com>2019-09-19 16:29:05 (GMT)
commit3368f3c6ae4140a0883e19350e672fd09c9db616 (patch)
tree0b4477fdd89aefa2b9d17e6a16c3f172f32a5660 /Objects
parent079931d12223ec98cbf53185b90db48efa61f93f (diff)
downloadcpython-3368f3c6ae4140a0883e19350e672fd09c9db616.zip
cpython-3368f3c6ae4140a0883e19350e672fd09c9db616.tar.gz
cpython-3368f3c6ae4140a0883e19350e672fd09c9db616.tar.bz2
bpo-38140: Make dict and weakref offsets opaque for C heap types (#16076)
* Make dict and weakref offsets opaque for C heap types * Add news
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index dfdac9e..94a4da2 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2853,15 +2853,27 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
PyTypeObject *type, *base;
PyType_Slot *slot;
- Py_ssize_t nmembers;
+ Py_ssize_t nmembers, weaklistoffset, dictoffset;
char *s, *res_start;
- nmembers = 0;
+ nmembers = weaklistoffset = dictoffset = 0;
for (slot = spec->slots; slot->slot; slot++) {
if (slot->slot == Py_tp_members) {
nmembers = 0;
for (memb = slot->pfunc; memb->name != NULL; memb++) {
nmembers++;
+ if (strcmp(memb->name, "__weaklistoffset__") == 0) {
+ // The PyMemberDef must be a Py_ssize_t and readonly
+ assert(memb->type == T_PYSSIZET);
+ assert(memb->flags == READONLY);
+ weaklistoffset = memb->offset;
+ }
+ if (strcmp(memb->name, "__dictoffset__") == 0) {
+ // The PyMemberDef must be a Py_ssize_t and readonly
+ assert(memb->type == T_PYSSIZET);
+ assert(memb->flags == READONLY);
+ dictoffset = memb->offset;
+ }
}
}
}
@@ -2990,6 +3002,17 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
res->ht_cached_keys = _PyDict_NewKeysForClass();
}
+ if (weaklistoffset) {
+ type->tp_weaklistoffset = weaklistoffset;
+ if (PyDict_DelItemString((PyObject *)type->tp_dict, "__weaklistoffset__") < 0)
+ goto fail;
+ }
+ if (dictoffset) {
+ type->tp_dictoffset = dictoffset;
+ if (PyDict_DelItemString((PyObject *)type->tp_dict, "__dictoffset__") < 0)
+ goto fail;
+ }
+
/* Set type.__module__ */
s = strrchr(spec->name, '.');
if (s != NULL) {