From fb305092a5d7894b41f122c1a1117b3abf4c567e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 7 Sep 2021 15:42:11 +0200 Subject: 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. --- .../Core and Builtins/2021-09-07-00-21-04.bpo-44348.f8w_Td.rst | 8 ++++++++ Objects/exceptions.c | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-09-07-00-21-04.bpo-44348.f8w_Td.rst 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 0000000..c222a07 --- /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 c6a7aa4..714039e 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 -- cgit v0.12