10000 bpo-45826: Fix a crash in suggestions.c by checking for `traceback is… · python/cpython@5d90c46 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5d90c46

Browse files
authored
bpo-45826: Fix a crash in suggestions.c by checking for traceback is None (GH-29590)
1 parent 736684b commit 5d90c46

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

Lib/test/test_exceptions.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,37 @@ def foo():
18851885

18861886
self.assertNotIn("something", err.getvalue())
18871887

1888+
def test_issue45826(self):
1889+
# regression test for bpo-45826
1890+
def f():
1891+
with self.assertRaisesRegex(NameError, 'aaa'):
1892+
aab
1893+
1894+
try:
1895+
f()
1896+
except self.failureException:
1897+
with support.captured_stderr() as err:
1898+
sys.__excepthook__(*sys.exc_info())
1899+
1900+
self.assertIn("aab", err.getvalue())
1901+
1902+
def test_issue45826_focused(self):
1903+
def f():
1904+
try:
1905+
nonsense
1906+
except BaseException as E:
1907+
E.with_traceback(None)
1908+
raise ZeroDivisionError()
1909+
1910+
try:
1911+
f()
1912+
except ZeroDivisionError:
1913+
with support.captured_stderr() as err:
1914+
sys.__excepthook__(*sys.exc_info())
1915+
1916+
self.assertIn("nonsense", err.getvalue())
1917+
self.assertIn("ZeroDivisionError", err.getvalue())
1918+
18881919

18891920
class AttributeErrorTests(unittest.TestCase):
18901921
def test_attributes(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``.

Python/suggestions.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
202202
PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference
203203
// Abort if we don't have a variable name or we have an invalid one
204204
// or if we don't have a traceback to work with
205-
if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) {
205+
if (name == NULL || !PyUnicode_CheckExact(name) ||
206+
traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type)
207+
) {
206208
return NULL;
207209
}
208210

209211
// Move to the traceback of the exception
210-
while (traceback->tb_next != NULL) {
211-
traceback = traceback->tb_next;
212+
while (1) {
213+
PyTracebackObject *next = traceback->tb_next;
214+
if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) {
215+
break;
216+
}
217+
else {
218+
traceback = next;
219+
}
212220
}
213221

214222
PyFrameObject *frame = traceback->tb_frame;

0 commit comments

Comments
 (0)
0