Skip to content

Commit 1603a10

Browse files
authored
pythonGH-93249: relax overly strict assertion on bounds->ar_start (pythonGH-93961)
1 parent cfb986a commit 1603a10

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

Lib/test/test_traceback.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from io import StringIO
55
import linecache
66
import sys
7+
import types
78
import inspect
89
import unittest
910
import re
@@ -1128,7 +1129,7 @@ def test_print_exception_bad_type_python(self):
11281129
class BaseExceptionReportingTests:
11291130

11301131
def get_exception(self, exception_or_callable):
1131-
if isinstance(exception_or_callable, Exception):
1132+
if isinstance(exception_or_callable, BaseException):
11321133
return exception_or_callable
11331134
try:
11341135
exception_or_callable()
@@ -1850,6 +1851,31 @@ def exc():
18501851
report = self.get_report(exc)
18511852
self.assertEqual(report, expected)
18521853

1854+
def test_KeyboardInterrupt_at_first_line_of_frame(self):
1855+
# see GH-93249
1856+
def f():
1857+
return sys._getframe()
1858+
1859+
tb_next = None
1860+
frame = f()
1861+
lasti = 0
1862+
lineno = f.__code__.co_firstlineno
1863+
tb = types.TracebackType(tb_next, frame, lasti, lineno)
1864+
1865+
exc = KeyboardInterrupt()
1866+
exc.__traceback__ = tb
1867+
1868+
expected = (f'Traceback (most recent call last):\n'
1869+
f' File "{__file__}", line {lineno}, in f\n'
1870+
f' def f():\n'
1871+
f'\n'
1872+
f'KeyboardInterrupt\n')
1873+
1874+
report = self.get_report(exc)
1875+
# remove trailing writespace:
1876+
report = '\n'.join([l.rstrip() for l in report.split('\n')])
1877+
self.assertEqual(report, expected)
1878+
18531879

18541880
class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase):
18551881
#

Objects/codeobject.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,11 @@ next_code_delta(PyCodeAddressRange *bounds)
826826
static int
827827
previous_code_delta(PyCodeAddressRange *bounds)
828828
{
829+
if (bounds->ar_start == 0) {
830+
// If we looking at the first entry, the
831+
// "previous" entry has an implicit length of 1.
832+
return 1;
833+
}
829834
const uint8_t *ptr = bounds->opaque.lo_next-1;
830835
while (((*ptr) & 128) == 0) {
831836
ptr--;
@@ -869,7 +874,7 @@ static void
869874
retreat(PyCodeAddressRange *bounds)
870875
{
871876
ASSERT_VALID_BOUNDS(bounds);
872-
assert(bounds->ar_start > 0);
877+
assert(bounds->ar_start >= 0);
873878
do {
874879
bounds->opaque.lo_next--;
875880
} while (((*bounds->opaque.lo_next) & 128) == 0);

0 commit comments

Comments
 (0)