Skip to content

Commit d5d7954

Browse files
authored
[3.6] bpo-30817: Fix PyErr_PrintEx() when no memory (GH-2526). (#4107)
(cherry picked from commit 66caacf)
1 parent d8f78a1 commit d5d7954

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

Lib/test/test_exceptions.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from test.support import (TESTFN, captured_stderr, check_impl_detail,
1212
check_warnings, cpython_only, gc_collect, run_unittest,
13-
no_tracing, unlink, import_module)
13+
no_tracing, unlink, import_module, script_helper)
1414

1515
class NaiveException(Exception):
1616
def __init__(self, x):
@@ -1104,6 +1104,23 @@ def test_unhandled(self):
11041104
self.assertIn("test message", report)
11051105
self.assertTrue(report.endswith("\n"))
11061106

1107+
@cpython_only
1108+
def test_memory_error_in_PyErr_PrintEx(self):
1109+
code = """if 1:
1110+
import _testcapi
1111+
class C(): pass
1112+
_testcapi.set_nomemory(0, %d)
1113+
C()
1114+
"""
1115+
1116+
# Issue #30817: Abort in PyErr_PrintEx() when no memory.
1117+
# Span a large range of tests as the CPython code always evolves with
1118+
# changes that add or remove memory allocations.
1119+
for i in range(1, 20):
1120+
rc, out, err = script_helper.assert_python_failure("-c", code % i)
1121+
self.assertIn(rc, (1, 120))
1122+
self.assertIn(b'MemoryError', err)
1123+
11071124

11081125
class ImportErrorTests(unittest.TestCase):
11091126

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`PyErr_PrintEx()` clears now the ignored exception that may be raised by
2+
`_PySys_SetObjectId()`, for example when no memory.

Python/pythonrun.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -624,9 +624,15 @@ PyErr_PrintEx(int set_sys_last_vars)
624624
return;
625625
/* Now we know v != NULL too */
626626
if (set_sys_last_vars) {
627-
_PySys_SetObjectId(&PyId_last_type, exception);
628-
_PySys_SetObjectId(&PyId_last_value, v);
629-
_PySys_SetObjectId(&PyId_last_traceback, tb);
627+
if (_PySys_SetObjectId(&PyId_last_type, exception) < 0) {
628+
PyErr_Clear();
629+
}
630+
if (_PySys_SetObjectId(&PyId_last_value, v) < 0) {
631+
PyErr_Clear();
632+
}
633+
if (_PySys_SetObjectId(&PyId_last_traceback, tb) < 0) {
634+
PyErr_Clear();
635+
}
630636
}
631637
hook = _PySys_GetObjectId(&PyId_excepthook);
632638
if (hook) {

0 commit comments

Comments
 (0)