Răsfoiți Sursa

Fixed #30405 -- Fixed source code mismatch crash in ExceptionReporter.

Hasan Ramezani 5 ani în urmă
părinte
comite
4b78546ef1
2 a modificat fișierele cu 40 adăugiri și 4 ștergeri
  1. 6 4
      django/views/debug.py
  2. 34 0
      tests/view_tests/tests/test_debug.py

+ 6 - 4
django/views/debug.py

@@ -384,10 +384,12 @@ class ExceptionReporter:
         lower_bound = max(0, lineno - context_lines)
         upper_bound = lineno + context_lines
 
-        pre_context = source[lower_bound:lineno]
-        context_line = source[lineno]
-        post_context = source[lineno + 1:upper_bound]
-
+        try:
+            pre_context = source[lower_bound:lineno]
+            context_line = source[lineno]
+            post_context = source[lineno + 1:upper_bound]
+        except IndexError:
+            return None, [], None, []
         return lower_bound, pre_context, context_line, post_context
 
     def get_traceback_frames(self):

+ 34 - 0
tests/view_tests/tests/test_debug.py

@@ -435,6 +435,40 @@ class ExceptionReporterTests(SimpleTestCase):
             text,
         )
 
+    def test_reporting_frames_source_not_match(self):
+        try:
+            source = "def funcName():\n    raise Error('Whoops')\nfuncName()"
+            namespace = {}
+            code = compile(source, 'generated', 'exec')
+            exec(code, namespace)
+        except Exception:
+            exc_type, exc_value, tb = sys.exc_info()
+        with mock.patch(
+            'django.views.debug.ExceptionReporter._get_source',
+            return_value=['wrong source'],
+        ):
+            request = self.rf.get('/test_view/')
+            reporter = ExceptionReporter(request, exc_type, exc_value, tb)
+            frames = reporter.get_traceback_frames()
+            last_frame = frames[-1]
+            self.assertEqual(last_frame['context_line'], '<source code not available>')
+            self.assertEqual(last_frame['filename'], 'generated')
+            self.assertEqual(last_frame['function'], 'funcName')
+            self.assertEqual(last_frame['lineno'], 2)
+            html = reporter.get_traceback_html()
+            self.assertIn('generated in funcName, line 2', html)
+            self.assertIn(
+                '"generated", line 2, in funcName\n'
+                '    &lt;source code not available&gt;',
+                html,
+            )
+            text = reporter.get_traceback_text()
+            self.assertIn(
+                '"generated", line 2, in funcName\n'
+                '    <source code not available>',
+                text,
+            )
+
     def test_reporting_frames_for_cyclic_reference(self):
         try:
             def test_func():