|
Expand Up
|
@@ -41,12 +41,20 @@ get_type_attr_as_size(PyTypeObject *tp, PyObject *name) |
|
|
get_type_attr_as_size(tp, &_Py_ID(n_sequence_fields)) |
|
|
#define REAL_SIZE_TP(tp) \ |
|
|
get_type_attr_as_size(tp, &_Py_ID(n_fields)) |
|
|
#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op)) |
|
|
#define REAL_SIZE(op) get_real_size((PyObject *)op) |
|
|
|
|
|
#define UNNAMED_FIELDS_TP(tp) \ |
|
|
get_type_attr_as_size(tp, &_Py_ID(n_unnamed_fields)) |
|
|
#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op)) |
|
|
|
|
|
static Py_ssize_t |
|
|
get_real_size(PyObject *op) |
|
|
{ |
|
|
// Compute the real size from the visible size (i.e., Py_SIZE()) and the |
|
|
// number of non-sequence fields accounted for in tp_basicsize. |
|
|
Py_ssize_t hidden = Py_TYPE(op)->tp_basicsize - offsetof(PyStructSequence, ob_item); |
|
|
return Py_SIZE(op) + hidden / sizeof(PyObject *); |
|
|
} |
|
|
|
|
|
PyObject * |
|
|
PyStructSequence_New(PyTypeObject *type) |
|
Expand Down
Expand Up
|
@@ -120,6 +128,9 @@ structseq_dealloc(PyStructSequence *obj) |
|
|
PyObject_GC_UnTrack(obj); |
|
|
|
|
|
PyTypeObject *tp = Py_TYPE(obj); |
|
|
// gh-122527: We can't use REAL_SIZE_TP() or any macros that access the |
|
|
// type's dictionary here, because the dictionary may have already been |
|
|
// cleared by the garbage collector. |
|
|
size = REAL_SIZE(obj); |
|
|
for (i = 0; i < size; ++i) { |
|
|
Py_XDECREF(obj->ob_item[i]); |
|
Expand Down
Expand Up
|
@@ -565,10 +576,14 @@ initialize_members(PyStructSequence_Desc *desc, |
|
|
|
|
|
static void |
|
|
initialize_static_fields(PyTypeObject *type, PyStructSequence_Desc *desc, |
|
|
PyMemberDef *tp_members, unsigned long tp_flags) |
|
|
PyMemberDef *tp_members, Py_ssize_t n_members, |
|
|
unsigned long tp_flags) |
|
|
{ |
|
|
type->tp_name = desc->name; |
|
|
type->tp_basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); |
|
|
// Account for hidden members in tp_basicsize because they are not |
|
|
// included in the variable size. |
|
|
Py_ssize_t n_hidden = n_members - desc->n_in_sequence; |
|
|
type->tp_basicsize = sizeof(PyStructSequence) + (n_hidden - 1) * sizeof(PyObject *); |
|
|
type->tp_itemsize = sizeof(PyObject *); |
|
|
type->tp_dealloc = (destructor)structseq_dealloc; |
|
|
type->tp_repr = (reprfunc)structseq_repr; |
|
Expand Down
Expand Up
|
@@ -621,7 +636,7 @@ _PyStructSequence_InitBuiltinWithFlags(PyInterpreterState *interp, |
|
|
if (members == NULL) { |
|
|
goto error; |
|
|
} |
|
|
initialize_static_fields(type, desc, members, tp_flags); |
|
|
initialize_static_fields(type, desc, members, n_members, tp_flags); |
|
|
|
|
|
_Py_SetImmortal((PyObject *)type); |
|
|
} |
|
Expand Down
Expand Up
|
@@ -684,7 +699,7 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) |
|
|
if (members == NULL) { |
|
|
return -1; |
|
|
} |
|
|
initialize_static_fields(type, desc, members, 0); |
|
|
initialize_static_fields(type, desc, members, n_members, 0); |
|
|
if (initialize_static_type(type, desc, n_members, n_unnamed_members) < 0) { |
|
|
PyMem_Free(members); |
|
|
return -1; |
|
Expand Down
Expand Up
|
@@ -760,7 +775,8 @@ _PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags) |
|
|
/* The name in this PyType_Spec is statically allocated so it is */ |
|
|
/* expected that it'll outlive the PyType_Spec */ |
|
|
spec.name = desc->name; |
|
|
spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *); |
|
|
Py_ssize_t hidden = n_members - desc->n_in_sequence; |
|
|
spec.basicsize = (int)(sizeof(PyStructSequence) + (hidden - 1) * sizeof(PyObject *)); |
|
|
spec.itemsize = sizeof(PyObject *); |
|
|
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags; |
|
|
spec.slots = slots; |
|
Expand Down
|
|