mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
bpo-35983: skip trashcan for subclasses (GH-11841)
Add new trashcan macros to deal with a double deallocation that could occur when the `tp_dealloc` of a subclass calls the `tp_dealloc` of a base class and that base class uses the trashcan mechanism. Patch by Jeroen Demeyer.
This commit is contained in:
parent
a2fedd8c91
commit
351c67416b
15 changed files with 189 additions and 121 deletions
|
@ -5451,6 +5451,76 @@ recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
}
|
||||
|
||||
|
||||
/* Test bpo-35983: create a subclass of "list" which checks that instances
|
||||
* are not deallocated twice */
|
||||
|
||||
typedef struct {
|
||||
PyListObject list;
|
||||
int deallocated;
|
||||
} MyListObject;
|
||||
|
||||
static PyObject *
|
||||
MyList_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* op = PyList_Type.tp_new(type, args, kwds);
|
||||
((MyListObject*)op)->deallocated = 0;
|
||||
return op;
|
||||
}
|
||||
|
||||
void
|
||||
MyList_dealloc(MyListObject* op)
|
||||
{
|
||||
if (op->deallocated) {
|
||||
/* We cannot raise exceptions here but we still want the testsuite
|
||||
* to fail when we hit this */
|
||||
Py_FatalError("MyList instance deallocated twice");
|
||||
}
|
||||
op->deallocated = 1;
|
||||
PyList_Type.tp_dealloc((PyObject *)op);
|
||||
}
|
||||
|
||||
static PyTypeObject MyList_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"MyList",
|
||||
sizeof(MyListObject),
|
||||
0,
|
||||
(destructor)MyList_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* &PyList_Type */ /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
MyList_new, /* tp_new */
|
||||
};
|
||||
|
||||
|
||||
/* Test PEP 560 */
|
||||
|
||||
typedef struct {
|
||||
|
@ -5564,6 +5634,12 @@ PyInit__testcapi(void)
|
|||
Py_INCREF(&awaitType);
|
||||
PyModule_AddObject(m, "awaitType", (PyObject *)&awaitType);
|
||||
|
||||
MyList_Type.tp_base = &PyList_Type;
|
||||
if (PyType_Ready(&MyList_Type) < 0)
|
||||
return NULL;
|
||||
Py_INCREF(&MyList_Type);
|
||||
PyModule_AddObject(m, "MyList", (PyObject *)&MyList_Type);
|
||||
|
||||
if (PyType_Ready(&GenericAlias_Type) < 0)
|
||||
return NULL;
|
||||
Py_INCREF(&GenericAlias_Type);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue