summaryrefslogtreecommitdiff
path: root/Objects/typeobject.c
diff options
context:
space:
mode:
authorEddie Elizondo <eduardo.elizondorueda@gmail.com>2018-11-13 04:09:31 -0800
committerPetr Viktorin <encukou@gmail.com>2018-11-13 13:09:31 +0100
commit474eedfb3d1b6fecbd749f36bf4a987cf4a00b44 (patch)
tree755905c5417d597c1a148fb719bbe83c10013649 /Objects/typeobject.c
parent1a6be91e6fd65ce9cb88cbbbb193db7e92ec6076 (diff)
downloadcpython-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.c28
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.