diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-07-00-21-04.bpo-44348.f8w_Td.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-00-21-04.bpo-44348.f8w_Td.rst new file mode 100644 index 00000000000000..c222a07725b8a3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-07-00-21-04.bpo-44348.f8w_Td.rst @@ -0,0 +1,8 @@ +The deallocator function of the :exc:`BaseException` type now uses the +trashcan mecanism to prevent stack overflow. For example, when a +:exc:`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. Patch by Victor Stinner. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index c6a7aa4aeccf04..714039ee1abca1 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -89,9 +89,14 @@ BaseException_clear(PyBaseExceptionObject *self) static void BaseException_dealloc(PyBaseExceptionObject *self) { - _PyObject_GC_UNTRACK(self); + PyObject_GC_UnTrack(self); + // bpo-44348: The trashcan mecanism prevents stack overflow when deleting + // long chains of exceptions. For example, exceptions can be chained + // through the __context__ attributes or the __traceback__ attribute. + Py_TRASHCAN_BEGIN(self, BaseException_dealloc) BaseException_clear(self); Py_TYPE(self)->tp_free((PyObject *)self); + Py_TRASHCAN_END } static int