Skip to content

Commit 21d60eb

Browse files
iritkatrielpython-sidebar
authored andcommitted
pythongh-102056: Fix a few bugs in error handling of exception printing code (python#102078)
1 parent 43b4094 commit 21d60eb

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

Lib/test/test_threading.py

+31
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,37 @@ def run():
15231523
self.assertEqual(out, b'')
15241524
self.assertNotIn("Unhandled exception", err.decode())
15251525

1526+
def test_print_exception_gh_102056(self):
1527+
# This used to crash. See gh-102056.
1528+
script = r"""if True:
1529+
import time
1530+
import threading
1531+
import _thread
1532+
1533+
def f():
1534+
try:
1535+
f()
1536+
except RecursionError:
1537+
f()
1538+
1539+
def g():
1540+
try:
1541+
raise ValueError()
1542+
except* ValueError:
1543+
f()
1544+
1545+
def h():
1546+
time.sleep(1)
1547+
_thread.interrupt_main()
1548+
1549+
t = threading.Thread(target=h)
1550+
t.start()
1551+
g()
1552+
t.join()
1553+
"""
1554+
1555+
assert_python_failure("-c", script)
1556+
15261557
def test_bare_raise_in_brand_new_thread(self):
15271558
def bare_raise():
15281559
raise
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix error handling bugs in interpreter's exception printing code, which could cause a crash on infinite recursion.

Python/pythonrun.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -1246,8 +1246,7 @@ print_chained(struct exception_print_context* ctx, PyObject *value,
12461246
const char * message, const char *tag)
12471247
{
12481248
PyObject *f = ctx->file;
1249-
1250-
if (_Py_EnterRecursiveCall(" in print_chained") < 0) {
1249+
if (_Py_EnterRecursiveCall(" in print_chained")) {
12511250
return -1;
12521251
}
12531252
bool need_close = ctx->need_close;
@@ -1374,7 +1373,9 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
13741373
if (ctx->exception_group_depth == 0) {
13751374
ctx->exception_group_depth += 1;
13761375
}
1377-
print_exception(ctx, value);
1376+
if (print_exception(ctx, value) < 0) {
1377+
return -1;
1378+
}
13781379

13791380
PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs;
13801381
assert(excs && PyTuple_Check(excs));
@@ -1424,7 +1425,7 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
14241425
PyObject *exc = PyTuple_GET_ITEM(excs, i);
14251426

14261427
if (!truncated) {
1427-
if (_Py_EnterRecursiveCall(" in print_exception_group") != 0) {
1428+
if (_Py_EnterRecursiveCall(" in print_exception_group")) {
14281429
return -1;
14291430
}
14301431
int res = print_exception_recursive(ctx, exc);
@@ -1477,22 +1478,30 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
14771478
static int
14781479
print_exception_recursive(struct exception_print_context *ctx, PyObject *value)
14791480
{
1481+
if (_Py_EnterRecursiveCall(" in print_exception_recursive")) {
1482+
return -1;
1483+
}
14801484
if (ctx->seen != NULL) {
14811485
/* Exception chaining */
14821486
if (print_exception_cause_and_context(ctx, value) < 0) {
1483-
return -1;
1487+
goto error;
14841488
}
14851489
}
14861490
if (!_PyBaseExceptionGroup_Check(value)) {
14871491
if (print_exception(ctx, value) < 0) {
1488-
return -1;
1492+
goto error;
14891493
}
14901494
}
14911495
else if (print_exception_group(ctx, value) < 0) {
1492-
return -1;
1496+
goto error;
14931497
}
14941498
assert(!PyErr_Occurred());
1499+
1500+
_Py_LeaveRecursiveCall();
14951501
return 0;
1502+
error:
1503+
_Py_LeaveRecursiveCall();
1504+
return -1;
14961505
}
14971506

14981507
#define PyErr_MAX_GROUP_WIDTH 15

0 commit comments

Comments
 (0)