Skip to content

Commit e273b28

Browse files
committed
pythongh-143377: fix crashes in _format_TracebackException
1 parent e6bfe4d commit e273b28

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

Lib/test/test_crossinterp.py

Lines changed: 19 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,21 @@ 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 e: []):
1502+
_interpreters.capture_exception(ValueError())
1503+
1504+
with swap_attr(traceback.TracebackException, "format", lambda e: 1):
1505+
with support.catch_unraisable_exception() as cm:
1506+
_interpreters.capture_exception(ValueError())
1507+
self.assertEqual(cm.unraisable.exc_type, TypeError)
1508+
self.assertEqual(str(cm.unraisable.exc_value),
1509+
"can only join an iterable")
1510+
1511+
14941512
if __name__ == '__main__':
14951513
unittest.main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a crash when formatting exceptions for which
2+
:meth:`traceback.TracebackException.format` return an empty iterable. Patch
3+
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)