diff options
author | Eddie Elizondo <eduardo.elizondorueda@gmail.com> | 2018-11-13 04:09:31 -0800 |
---|---|---|
committer | Petr Viktorin <encukou@gmail.com> | 2018-11-13 13:09:31 +0100 |
commit | 474eedfb3d1b6fecbd749f36bf4a987cf4a00b44 (patch) | |
tree | 755905c5417d597c1a148fb719bbe83c10013649 /Objects/typeobject.c | |
parent | 1a6be91e6fd65ce9cb88cbbbb193db7e92ec6076 (diff) | |
download | cpython-git-474eedfb3d1b6fecbd749f36bf4a987cf4a00b44.tar.gz |
bpo-34784: Fix PyStructSequence_NewType with heap-allocated StructSequence (GH-9665)
Diffstat (limited to 'Objects/typeobject.c')
-rw-r--r-- | Objects/typeobject.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 682d44696e..4d599bf516 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2846,15 +2846,28 @@ static const short slotoffsets[] = { PyObject * PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) { - PyHeapTypeObject *res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, 0); - PyTypeObject *type, *base; + PyHeapTypeObject *res; + PyMemberDef *memb; PyObject *modname; - char *s; - char *res_start = (char*)res; + PyTypeObject *type, *base; + PyType_Slot *slot; + Py_ssize_t nmembers; + char *s, *res_start; + + nmembers = 0; + for (slot = spec->slots; slot->slot; slot++) { + if (slot->slot == Py_tp_members) { + for (memb = slot->pfunc; memb->name != NULL; memb++) { + nmembers++; + } + } + } + res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, nmembers); if (res == NULL) return NULL; + res_start = (char*)res; if (spec->name == NULL) { PyErr_SetString(PyExc_SystemError, @@ -2950,6 +2963,13 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) memcpy(tp_doc, old_doc, len); type->tp_doc = tp_doc; } + + /* Move the slots to the heap type itself */ + if (slot->slot == Py_tp_members) { + size_t len = Py_TYPE(type)->tp_itemsize * nmembers; + memcpy(PyHeapType_GET_MEMBERS(res), slot->pfunc, len); + type->tp_members = PyHeapType_GET_MEMBERS(res); + } } if (type->tp_dealloc == NULL) { /* It's a heap type, so needs the heap types' dealloc. |