Skip to content

Commit 8eabe60

Browse files
ambvsweeneyde
andauthored
[3.10] bpo-45826: Fix a crash in suggestions.c by checking for traceback is None (GH-29590) (GH-29602)
(cherry picked from commit 5d90c46) Co-authored-by: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com>
1 parent 563e458 commit 8eabe60

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
@@ -200,13 +200,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
200200
PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference
201201
// Abort if we don't have a variable name or we have an invalid one
202202
// or if we don't have a traceback to work with
203-
if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) {
203+
if (name == NULL || !PyUnicode_CheckExact(name) ||
204+
traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type)
205+
) {
204206
return NULL;
205207
}
206208

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

212220
PyFrameObject *frame = traceback->tb_frame;

0 commit comments

Comments
 (0)