Skip to content

Commit 9f7fa39

Browse files
committed
pythongh-143377: fix crashes in _interpreters.capture_exception
1 parent e6bfe4d commit 9f7fa39

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

Lib/test/test_crossinterp.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import contextlib
22
import itertools
33
import sys
4+
import traceback
45
import types
56
import unittest
67
import warnings
78

8-
from test.support import import_helper
9+
from test import support
10+
from test.support import import_helper, swap_attr
911

1012
_testinternalcapi = import_helper.import_module('_testinternalcapi')
1113
_interpreters = import_helper.import_module('_interpreters')
@@ -1491,5 +1493,27 @@ def test_builtin_objects(self):
14911493
])
14921494

14931495

1496+
class ExceptionTests(unittest.TestCase):
1497+
1498+
def test_capture_exception(self):
1499+
# Prevent crashes with incompatible TracebackException.format().
1500+
# Regression test for https://github.com/python/cpython/issues/143377.
1501+
with swap_attr(traceback.TracebackException, "format", lambda self: []):
1502+
try:
1503+
raise ValueError
1504+
except Exception as exc:
1505+
_interpreters.capture_exception(exc)
1506+
1507+
with swap_attr(traceback.TracebackException, "format", lambda self: 1):
1508+
try:
1509+
raise ValueError
1510+
except Exception as exc:
1511+
with support.catch_unraisable_exception() as cm:
1512+
_interpreters.capture_exception(exc)
1513+
self.assertEqual(cm.unraisable.exc_type, TypeError)
1514+
self.assertEqual(str(cm.unraisable.exc_value),
1515+
"can only join an iterable")
1516+
1517+
14941518
if __name__ == '__main__':
14951519
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in :func:`!_interpreters.capture_exception` when
2+
the exception is incorrectly formatted. Patch by Bénédikt Tran.

Python/crossinterp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,10 +1137,12 @@ _format_TracebackException(PyObject *tbexc)
11371137
if (formatted_obj == NULL) {
11381138
return NULL;
11391139
}
1140-
11411140
Py_ssize_t size = -1;
11421141
const char *formatted = _copy_string_obj_raw(formatted_obj, &size);
11431142
Py_DECREF(formatted_obj);
1143+
if (formatted == NULL || size == 0) {
1144+
return formatted;
1145+
}
11441146
// We remove trailing the newline added by TracebackException.format().
11451147
assert(formatted[size-1] == '\n');
11461148
((char *)formatted)[size-1] = '\0';

0 commit comments

Comments
 (0)