diff options
author | Mark Shannon <mark@hotpy.org> | 2022-08-03 17:56:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-03 17:56:24 (GMT) |
commit | 906e4509328917fe9951f85457897f6a841e0529 (patch) | |
tree | 0ee26881b28d07bc0ec00ae72e3af3f8f134f8a6 /Objects | |
parent | 89f52293281b6efc4ef666ef25e677683821f4b9 (diff) | |
download | cpython-906e4509328917fe9951f85457897f6a841e0529.zip cpython-906e4509328917fe9951f85457897f6a841e0529.tar.gz cpython-906e4509328917fe9951f85457897f6a841e0529.tar.bz2 |
GH-92678: Fix tp_dictoffset inheritance. (GH-95596)
* Add test for inheriting explicit __dict__ and weakref.
* Restore 3.10 behavior for multiple inheritance of C extension classes that store their dictionary at the end of the struct.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d33befc0..1980fcb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2316,6 +2316,11 @@ best_base(PyObject *bases) return base; } +#define ADDED_FIELD_AT_OFFSET(name, offset) \ + (type->tp_ ## name && (base->tp_ ##name == 0) && \ + type->tp_ ## name + sizeof(PyObject *) == (offset) && \ + type->tp_flags & Py_TPFLAGS_HEAPTYPE) + static int extra_ivars(PyTypeObject *type, PyTypeObject *base) { @@ -2328,10 +2333,18 @@ extra_ivars(PyTypeObject *type, PyTypeObject *base) return t_size != b_size || type->tp_itemsize != base->tp_itemsize; } - if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 && - type->tp_weaklistoffset + sizeof(PyObject *) == t_size && - type->tp_flags & Py_TPFLAGS_HEAPTYPE) + /* Check for __dict__ and __weakrefs__ slots in either order */ + if (ADDED_FIELD_AT_OFFSET(weaklistoffset, t_size)) { + t_size -= sizeof(PyObject *); + } + if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0 && + ADDED_FIELD_AT_OFFSET(dictoffset, t_size)) { t_size -= sizeof(PyObject *); + } + /* Check __weakrefs__ again, in case it precedes __dict__ */ + if (ADDED_FIELD_AT_OFFSET(weaklistoffset, t_size)) { + t_size -= sizeof(PyObject *); + } return t_size != b_size; } |