From cbd571e614bc17b4e486fcba7c1926b49383636c Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 1 May 2020 20:58:26 +0100 Subject: [PATCH 1/5] bpo-40458: Increase reserved stack space to prevent overflow crash on Windows --- .../Windows/2020-05-01-20-57-57.bpo-40458.Eb0ueI.rst | 1 + Modules/faulthandler.c | 11 ++++++++++- PCbuild/python_uwp.vcxproj | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Windows/2020-05-01-20-57-57.bpo-40458.Eb0ueI.rst diff --git a/Misc/NEWS.d/next/Windows/2020-05-01-20-57-57.bpo-40458.Eb0ueI.rst b/Misc/NEWS.d/next/Windows/2020-05-01-20-57-57.bpo-40458.Eb0ueI.rst new file mode 100644 index 00000000000000..4dc1ff480df87a --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-05-01-20-57-57.bpo-40458.Eb0ueI.rst @@ -0,0 +1 @@ +Increase reserved stack space to prevent overflow crash on Windows. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index e7a285033051df..02af630d3c1024 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -386,6 +386,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) const int fd = fatal_error.fd; DWORD code = exc_info->ExceptionRecord->ExceptionCode; DWORD flags = exc_info->ExceptionRecord->ExceptionFlags; + PyThreadState *tstate; if (faulthandler_ignore_exception(code)) { /* ignore the exception: call the next exception handler */ @@ -402,7 +403,15 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) case EXCEPTION_INT_DIVIDE_BY_ZERO: PUTS(fd, "int divide by zero"); break; case EXCEPTION_INT_OVERFLOW: PUTS(fd, "integer overflow"); break; case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break; - case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break; + case EXCEPTION_STACK_OVERFLOW: + PUTS(fd, "stack overflow"); + tstate = get_thread_state(); + if (tstate != NULL) { + PUTS(fd, " (recursion depth="); + _Py_DumpDecimal(fd, tstate->recursion_depth); + PUTS(fd, ")"); + } + break; default: PUTS(fd, "code 0x"); _Py_DumpHexadecimal(fd, code, 8); diff --git a/PCbuild/python_uwp.vcxproj b/PCbuild/python_uwp.vcxproj index 5ff120a0da331a..fb27e9e71222e3 100644 --- a/PCbuild/python_uwp.vcxproj +++ b/PCbuild/python_uwp.vcxproj @@ -95,6 +95,7 @@ windowsapp.lib;%(AdditionalDependencies) Console + 2000000 From a7a12ce5fa76087811f22b458c56a71095df7d3d Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 1 May 2020 20:59:38 +0100 Subject: [PATCH 2/5] Also update pythonw --- PCbuild/pythonw_uwp.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/PCbuild/pythonw_uwp.vcxproj b/PCbuild/pythonw_uwp.vcxproj index 828d0d1ccac217..e21e46a1b722ed 100644 --- a/PCbuild/pythonw_uwp.vcxproj +++ b/PCbuild/pythonw_uwp.vcxproj @@ -95,6 +95,7 @@ windowsapp.lib;%(AdditionalDependencies) Windows + 2000000 From 6588ebc4509519b178a0b3c43004d73fd9f99bab Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 1 May 2020 21:06:06 +0100 Subject: [PATCH 3/5] Avoid setting exception if overflow occurs outside of a Python thread --- Modules/faulthandler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 02af630d3c1024..cfd7b10cb0de8d 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -405,7 +405,8 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break; case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); - tstate = get_thread_state(); + /* call UncheckedGet directly to avoid setting exceptions */ + tstate = _PyThreadState_UncheckedGet(); if (tstate != NULL) { PUTS(fd, " (recursion depth="); _Py_DumpDecimal(fd, tstate->recursion_depth); From f06a32214efae1dc15b7fe9ea0d243c80d4b68f7 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 1 May 2020 21:26:10 +0100 Subject: [PATCH 4/5] Update test --- Lib/test/test_faulthandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index c64afe88c25d6c..f0dc8276cc8a60 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -757,7 +757,7 @@ def test_raise_exception(self): for exc, name in ( ('EXCEPTION_ACCESS_VIOLATION', 'access violation'), ('EXCEPTION_INT_DIVIDE_BY_ZERO', 'int divide by zero'), - ('EXCEPTION_STACK_OVERFLOW', 'stack overflow'), + ('EXCEPTION_STACK_OVERFLOW', r'stack overflow(\s+\(.+\))?'), ): self.check_windows_exception(f""" import faulthandler From 6c53dd4514a0954aa528cb15ac8fe1ef0e3279ba Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Tue, 5 May 2020 17:13:23 +0100 Subject: [PATCH 5/5] Revert improved diagnostics --- Lib/test/test_faulthandler.py | 2 +- Modules/faulthandler.c | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index f0dc8276cc8a60..c64afe88c25d6c 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -757,7 +757,7 @@ def test_raise_exception(self): for exc, name in ( ('EXCEPTION_ACCESS_VIOLATION', 'access violation'), ('EXCEPTION_INT_DIVIDE_BY_ZERO', 'int divide by zero'), - ('EXCEPTION_STACK_OVERFLOW', r'stack overflow(\s+\(.+\))?'), + ('EXCEPTION_STACK_OVERFLOW', 'stack overflow'), ): self.check_windows_exception(f""" import faulthandler diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index cfd7b10cb0de8d..e7a285033051df 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -386,7 +386,6 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) const int fd = fatal_error.fd; DWORD code = exc_info->ExceptionRecord->ExceptionCode; DWORD flags = exc_info->ExceptionRecord->ExceptionFlags; - PyThreadState *tstate; if (faulthandler_ignore_exception(code)) { /* ignore the exception: call the next exception handler */ @@ -403,16 +402,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info) case EXCEPTION_INT_DIVIDE_BY_ZERO: PUTS(fd, "int divide by zero"); break; case EXCEPTION_INT_OVERFLOW: PUTS(fd, "integer overflow"); break; case EXCEPTION_IN_PAGE_ERROR: PUTS(fd, "page error"); break; - case EXCEPTION_STACK_OVERFLOW: - PUTS(fd, "stack overflow"); - /* call UncheckedGet directly to avoid setting exceptions */ - tstate = _PyThreadState_UncheckedGet(); - if (tstate != NULL) { - PUTS(fd, " (recursion depth="); - _Py_DumpDecimal(fd, tstate->recursion_depth); - PUTS(fd, ")"); - } - break; + case EXCEPTION_STACK_OVERFLOW: PUTS(fd, "stack overflow"); break; default: PUTS(fd, "code 0x"); _Py_DumpHexadecimal(fd, code, 8);