summaryrefslogtreecommitdiffstats
path: root/Lib/dis.py
diff options
context:
space:
mode:
authorT. Wouters <thomas@python.org>2019-09-28 14:49:15 (GMT)
committerGregory P. Smith <greg@krypto.org>2019-09-28 14:49:15 (GMT)
commitc8165036f374cd2ee64d4314eeb2514f7acb5026 (patch)
tree457ae87d81e9ec7ee50e538302d069e28cf79287 /Lib/dis.py
parent7774d7831e8809795c64ce27f7df52674581d298 (diff)
downloadcpython-c8165036f374cd2ee64d4314eeb2514f7acb5026.zip
cpython-c8165036f374cd2ee64d4314eeb2514f7acb5026.tar.gz
cpython-c8165036f374cd2ee64d4314eeb2514f7acb5026.tar.bz2
bpo-38115: Deal with invalid bytecode offsets in lnotab (GH-16079)
Document that lnotab can contain invalid bytecode offsets (because of terrible reasons that are difficult to fix). Make dis.findlinestarts() ignore invalid offsets in lnotab. All other uses of lnotab in CPython (various reimplementations of addr2line or line2addr in Python, C and gdb) already ignore this, because they take an address to look for, instead. Add tests for the result of dis.findlinestarts() on wacky constructs in test_peepholer.py, because it's the easiest place to add them.
Diffstat (limited to 'Lib/dis.py')
-rw-r--r--Lib/dis.py5
1 files changed, 5 insertions, 0 deletions
diff --git a/Lib/dis.py b/Lib/dis.py
index a25fb2b..10e5f7f 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -454,6 +454,7 @@ def findlinestarts(code):
"""
byte_increments = code.co_lnotab[0::2]
line_increments = code.co_lnotab[1::2]
+ bytecode_len = len(code.co_code)
lastlineno = None
lineno = code.co_firstlineno
@@ -464,6 +465,10 @@ def findlinestarts(code):
yield (addr, lineno)
lastlineno = lineno
addr += byte_incr
+ if addr >= bytecode_len:
+ # The rest of the lnotab byte offsets are past the end of
+ # the bytecode, so the lines were optimized away.
+ return
if line_incr >= 0x80:
# line_increments is an array of 8-bit signed integers
line_incr -= 0x100