Skip to content

Commit

Permalink
bpo-45826: Fix a crash in suggestions.c by checking for `traceback is…
Browse files Browse the repository at this point in the history
… None` (pythonGH-29590)
  • Loading branch information
sweeneyde authored Nov 17, 2021
1 parent 736684b commit 5d90c46
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
31 changes: 31 additions & 0 deletions Lib/test/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,37 @@ def foo():

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

def test_issue45826(self):
# regression test for bpo-45826
def f():
with self.assertRaisesRegex(NameError, 'aaa'):
aab

try:
f()
except self.failureException:
with support.captured_stderr() as err:
sys.__excepthook__(*sys.exc_info())

self.assertIn("aab", err.getvalue())

def test_issue45826_focused(self):
def f():
try:
nonsense
except BaseException as E:
E.with_traceback(None)
raise ZeroDivisionError()

try:
f()
except ZeroDivisionError:
with support.captured_stderr() as err:
sys.__excepthook__(*sys.exc_info())

self.assertIn("nonsense", err.getvalue())
self.assertIn("ZeroDivisionError", err.getvalue())


class AttributeErrorTests(unittest.TestCase):
def test_attributes(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``.
14 changes: 11 additions & 3 deletions Python/suggestions.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,21 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference
// Abort if we don't have a variable name or we have an invalid one
// or if we don't have a traceback to work with
if (name == NULL || traceback == NULL || !PyUnicode_CheckExact(name)) {
if (name == NULL || !PyUnicode_CheckExact(name) ||
traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type)
) {
return NULL;
}

// Move to the traceback of the exception
while (traceback->tb_next != NULL) {
traceback = traceback->tb_next;
while (1) {
PyTracebackObject *next = traceback->tb_next;
if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) {
break;
}
else {
traceback = next;
}
}

PyFrameObject *frame = traceback->tb_frame;
Expand Down

0 comments on commit 5d90c46

Please sign in to comment.