Christian Tismer's "trashcan" patch:

Added wrapping macros to dictobject.c, listobject.c, tupleobject.c,
frameobject.c, traceback.c that safely prevends core dumps
on stack overflow. Macros and functions in object.c, object.h.
The method is an "elevator destructor" that turns cascading
deletes into tail recursive behavior when some limit is hit.
This commit is contained in:
Guido van Rossum 2000-03-13 16:01:29 +00:00
parent 96a45adf80
commit d724b23420
7 changed files with 104 additions and 1 deletions

View file

@ -479,6 +479,7 @@ dict_dealloc(mp)
{
register int i;
register dictentry *ep;
Py_TRASHCAN_SAFE_BEGIN(mp)
for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
if (ep->me_key != NULL) {
Py_DECREF(ep->me_key);
@ -489,6 +490,7 @@ dict_dealloc(mp)
}
PyMem_XDEL(mp->ma_table);
PyMem_DEL(mp);
Py_TRASHCAN_SAFE_END(mp)
}
static int

View file

@ -103,6 +103,7 @@ frame_dealloc(f)
int i;
PyObject **fastlocals;
Py_TRASHCAN_SAFE_BEGIN(f)
/* Kill all local variables */
fastlocals = f->f_localsplus;
for (i = f->f_nlocals; --i >= 0; ++fastlocals) {
@ -120,6 +121,7 @@ frame_dealloc(f)
Py_XDECREF(f->f_exc_traceback);
f->f_back = free_list;
free_list = f;
Py_TRASHCAN_SAFE_END(f)
}
PyTypeObject PyFrame_Type = {

View file

@ -215,6 +215,7 @@ list_dealloc(op)
PyListObject *op;
{
int i;
Py_TRASHCAN_SAFE_BEGIN(op)
if (op->ob_item != NULL) {
/* Do it backwards, for Christian Tismer.
There's a simple test case where somehow this reduces
@ -227,6 +228,7 @@ list_dealloc(op)
free((ANY *)op->ob_item);
}
free((ANY *)op);
Py_TRASHCAN_SAFE_END(op)
}
static int

View file

@ -906,3 +906,48 @@ Py_ReprLeave(obj)
}
}
}
/*
trashcan
CT 2k0130
non-recursively destroy nested objects
CT 2k0223
everything is now done in a macro.
CT 2k0305
modified to use functions, after Tim Peter's suggestion.
CT 2k0309
modified to restore a possible error.
*/
int _PyTrash_delete_nesting = 0;
PyObject * _PyTrash_delete_later = NULL;
void
_PyTrash_deposit_object(op)
PyObject *op;
{
PyObject *error_type, *error_value, *error_traceback;
PyErr_Fetch(&error_type, &error_value, &error_traceback);
if (!_PyTrash_delete_later)
_PyTrash_delete_later = PyList_New(0);
if (_PyTrash_delete_later)
PyList_Append(_PyTrash_delete_later, (PyObject *)op);
PyErr_Restore(error_type, error_value, error_traceback);
}
void
_PyTrash_destroy_list()
{
while (_PyTrash_delete_later) {
PyObject *shredder = _PyTrash_delete_later;
_PyTrash_delete_later = NULL;
++_PyTrash_delete_nesting;
Py_DECREF(shredder);
--_PyTrash_delete_nesting;
}
}

View file

@ -172,6 +172,7 @@ tupledealloc(op)
{
register int i;
Py_TRASHCAN_SAFE_BEGIN(op)
if (op->ob_size > 0) {
i = op->ob_size;
while (--i >= 0)
@ -180,11 +181,13 @@ tupledealloc(op)
if (op->ob_size < MAXSAVESIZE) {
op->ob_item[0] = (PyObject *) free_tuples[op->ob_size];
free_tuples[op->ob_size] = op;
return;
goto done; /* return */
}
#endif
}
free((ANY *)op);
done:
Py_TRASHCAN_SAFE_END(op)
}
static int