Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r88479:038ed5ec2571
Date: 2016-11-19 17:39 +0100
http://bitbucket.org/pypy/pypy/changeset/038ed5ec2571/
Log: Test and fix for setting f_lineno
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -647,51 +647,43 @@
raise oefmt(space.w_ValueError,
"can't jump to 'except' line as there's no exception")
- # Don't jump into or out of a finally block.
- # Unlike CPython, we can't jump into or out of an except block
- # either---there would be a mess with SysExcInfoRestorer.
+ # Don't jump inside or out of an except or a finally block.
+ # Note that CPython doesn't check except blocks,
+ # but that results in crashes (tested on 3.5.2+).
f_lasti_handler_addr = -1
new_lasti_handler_addr = -1
- blockstack = [-1] # list of odd length:
- # * addr of most recent outermost handler
- # [ * addr of start of outermost block
- # * addr of most recent handler in that block
- # (last two items repeated) ]
+ blockstack = [] # current blockstack (addresses of SETUP_*)
+ endblock = [-1] # current finally/except block stack
addr = 0
while addr < len(code):
op = ord(code[addr])
if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH,
SETUP_ASYNC_WITH):
blockstack.append(addr)
- blockstack.append(-1)
elif op == POP_BLOCK:
- if len(blockstack) < 3:
+ if len(blockstack) == 0:
raise oefmt(space.w_SystemError,
- "blocks not properly nested in this bytecode")
- blockstack.pop()
+ "POP_BLOCK not properly nested in this bytecode")
setup_op = ord(code[blockstack.pop()])
if setup_op != SETUP_LOOP:
- blockstack[-1] = addr
- elif op == END_FINALLY: # "async for" nests blocks
- blockstack[-1] = -1 # strangely, careful here
+ endblock.append(addr)
+ elif op == END_FINALLY:
+ if len(endblock) <= 1:
+ raise oefmt(space.w_SystemError,
+ "END_FINALLY not properly nested in this bytecode")
+ endblock.pop()
- if addr == new_lasti or addr == self.last_instr:
- ii = len(blockstack) - 1
- while ii > 0 and blockstack[ii] == -1:
- ii -= 2
- assert ii >= 0
- handler_addr = blockstack[ii]
- if addr == new_lasti:
- new_lasti_handler_addr = handler_addr
- if addr == self.last_instr:
- f_lasti_handler_addr = handler_addr
+ if addr == new_lasti:
+ new_lasti_handler_addr = endblock[-1]
+ if addr == self.last_instr:
+ f_lasti_handler_addr = endblock[-1]
if op >= HAVE_ARGUMENT:
addr += 3
else:
addr += 1
- if len(blockstack) != 1:
+ if len(blockstack) != 0 or len(endblock) != 1:
raise oefmt(space.w_SystemError,
"blocks not properly nested in this bytecode")
diff --git a/pypy/interpreter/test/test_pyframe.py
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -121,6 +121,30 @@
assert str(errors[0]).startswith(
"can't jump into or out of an 'expect' or 'finally' block")
+ def test_f_lineno_set_3(self):
+ def jump_in_nested_finally(output):
+ try:
+ output.append(2)
+ finally:
+ output.append(4)
+ try:
+ output.append(6)
+ finally:
+ output.append(8)
+ output.append(9)
+ output = []
+
+ def tracer(f, event, *args):
+ if event == 'line' and len(output) == 1:
+ f.f_lineno += 5
+ return tracer
+
+ import sys
+ sys.settrace(tracer)
+ jump_in_nested_finally(output)
+ sys.settrace(None)
+ assert output == [2, 9]
+
def test_f_lineno_set_firstline(self):
r"""
seen = []
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit