]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.10] bpo-45826: Fix a crash in suggestions.c by checking for `traceback is None...
authorŁukasz Langa <lukasz@langa.pl>
Thu, 18 Nov 2021 00:28:04 +0000 (01:28 +0100)
committerGitHub <noreply@github.com>
Thu, 18 Nov 2021 00:28:04 +0000 (01:28 +0100)
(cherry picked from commit 5d90c467c02ffefdb13c1abc83a171db1a99ffad)

Co-authored-by: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com>
Lib/test/test_exceptions.py
Misc/NEWS.d/next/Core and Builtins/2021-11-17-08-05-27.bpo-45826.OERoTm.rst [new file with mode: 0644]
Python/suggestions.c

index 4930c57d3fd7ef03d394a6a9b33b9e3648d78bfc..8419f582cbdb93d1c259ea6c3f2d88bdaa7fbf9f 100644 (file)
@@ -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 (file)
index 0000000..f04373b
--- /dev/null
@@ -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
index 7fd62fbfabf6425744d468031e0085c2685c81fb..4e2f9055779b277221d92123cca8bda12b73095e 100644 (file)
@@ -200,13 +200,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;