diff options
author | Mark Shannon <mark@hotpy.org> | 2022-08-17 11:50:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-17 11:50:53 (GMT) |
commit | b73e3b6d4a6c505f2869ae4d0a4a93241450cf32 (patch) | |
tree | 4225e01b62828975bd57361b2d1137bae9aa754e /Objects | |
parent | 0f2b469ce1a6f123ad9e151b1771651b3e1d2de6 (diff) | |
download | cpython-b73e3b6d4a6c505f2869ae4d0a4a93241450cf32.zip cpython-b73e3b6d4a6c505f2869ae4d0a4a93241450cf32.tar.gz cpython-b73e3b6d4a6c505f2869ae4d0a4a93241450cf32.tar.bz2 |
GH-95589: Dont crash when subclassing extension classes with multiple inheritance (GH-96028)
* Treat tp_weakref and tp_dictoffset like other opaque slots for multiple inheritance.
* Document Py_TPFLAGS_MANAGED_DICT and Py_TPFLAGS_MANAGED_WEAKREF in what's new.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 45 |
1 files changed, 13 insertions, 32 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f796a91..e8c36cf 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2330,36 +2330,13 @@ 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) +shape_differs(PyTypeObject *t1, PyTypeObject *t2) { - size_t t_size = type->tp_basicsize; - size_t b_size = base->tp_basicsize; - - assert(t_size >= b_size); /* Else type smaller than base! */ - if (type->tp_itemsize || base->tp_itemsize) { - /* If itemsize is involved, stricter rules */ - return t_size != b_size || - type->tp_itemsize != base->tp_itemsize; - } - /* 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; + return ( + t1->tp_basicsize != t2->tp_basicsize || + t1->tp_itemsize != t2->tp_itemsize + ); } static PyTypeObject * @@ -2367,14 +2344,18 @@ solid_base(PyTypeObject *type) { PyTypeObject *base; - if (type->tp_base) + if (type->tp_base) { base = solid_base(type->tp_base); - else + } + else { base = &PyBaseObject_Type; - if (extra_ivars(type, base)) + } + if (shape_differs(type, base)) { return type; - else + } + else { return base; + } } static void object_dealloc(PyObject *); |