Skip to content

Commit fb30509

Browse files
authored
bpo-44348: BaseException deallocator uses trashcan (GH-28190)
The deallocator function of the BaseException type now uses the trashcan mecanism to prevent stack overflow. For example, when a RecursionError instance is raised, it can be linked to another RecursionError through the __context__ attribute or the __traceback__ attribute, and then a chain of exceptions is created. When the chain is destroyed, nested deallocator function calls can crash with a stack overflow if the chain is too long compared to the available stack memory.
1 parent 979336d commit fb30509

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
The deallocator function of the :exc:`BaseException` type now uses the
2+
trashcan mecanism to prevent stack overflow. For example, when a
3+
:exc:`RecursionError` instance is raised, it can be linked to another
4+
RecursionError through the ``__context__`` attribute or the
5+
``__traceback__`` attribute, and then a chain of exceptions is created. When
6+
the chain is destroyed, nested deallocator function calls can crash with a
7+
stack overflow if the chain is too long compared to the available stack
8+
memory. Patch by Victor Stinner.

Objects/exceptions.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,14 @@ BaseException_clear(PyBaseExceptionObject *self)
8989
static void
9090
BaseException_dealloc(PyBaseExceptionObject *self)
9191
{
92-
_PyObject_GC_UNTRACK(self);
92+
PyObject_GC_UnTrack(self);
93+
// bpo-44348: The trashcan mecanism prevents stack overflow when deleting
94+
// long chains of exceptions. For example, exceptions can be chained
95+
// through the __context__ attributes or the __traceback__ attribute.
96+
Py_TRASHCAN_BEGIN(self, BaseException_dealloc)
9397
BaseException_clear(self);
9498
Py_TYPE(self)->tp_free((PyObject *)self);
99+
Py_TRASHCAN_END
95100
}
96101

97102
static int

0 commit comments

Comments
 (0)