summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-08-17 11:50:53 (GMT)
committerGitHub <noreply@github.com>2022-08-17 11:50:53 (GMT)
commitb73e3b6d4a6c505f2869ae4d0a4a93241450cf32 (patch)
tree4225e01b62828975bd57361b2d1137bae9aa754e /Objects
parent0f2b469ce1a6f123ad9e151b1771651b3e1d2de6 (diff)
downloadcpython-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.c45
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 *);