aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_exceptions.py31
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst1
-rw-r--r--Python/suggestions.c14
3 files changed, 43 insertions, 3 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 0f8a8f134b..098804fad5 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -1885,6 +1885,37 @@ class NameErrorTests(unittest.TestCase):
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):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst
new file mode 100644
index 0000000000..f04373bf2f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst
@@ -0,0 +1 @@
+Fixed a crash when calling ``.with_traceback(None)`` on ``NameError``. This occurs internally in ``unittest.TestCase.assertRaises()``. \ No newline at end of file
diff --git a/Python/suggestions.c b/Python/suggestions.c
index 81976ff4f2..d9e69fa7e0 100644
--- a/Python/suggestions.c
+++ b/Python/suggestions.c
@@ -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;