Skip to content

Commit a86304e

Browse files
author
condut
committed
Fix jumping out of with blocks in py26 (and added test)
Plus added extra test from master
1 parent 1595766 commit a86304e

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

goto.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ def _find_labels_and_gotos(code):
167167
for_exits = []
168168
excepts = []
169169
finallies = []
170+
last_block = None
170171

171172
opname0 = oparg0 = offset0 = None
172173
opname1 = oparg1 = offset1 = None # the main one we're looking at each loop iteration
@@ -187,7 +188,7 @@ def replace_block(old_block, new_block):
187188

188189
def pop_block():
189190
if block_stack:
190-
block_stack.pop()
191+
return block_stack.pop()
191192
else:
192193
_warn_bug("can't pop block")
193194

@@ -198,14 +199,14 @@ def pop_block_of_type(type):
198199
replace_block(block_stack[-1], (type, block_stack[-1][1]))
199200
else:
200201
_warn_bug("mismatched block type")
201-
pop_block()
202+
return pop_block()
202203

203204
for opname4, oparg4, offset4 in _parse_instructions(code.co_code, 3):
204205
endoffset1 = offset2
205206

206207
# check for special offsets
207208
if for_exits and offset1 == for_exits[-1]:
208-
pop_block()
209+
last_block = pop_block()
209210
for_exits.pop()
210211
if excepts and offset1 == excepts[-1]:
211212
block_counter += 1
@@ -243,14 +244,17 @@ def pop_block_of_type(type):
243244
block_stack.append((opname1, block_counter))
244245
for_exits.append(endoffset1 + oparg1)
245246
elif opname1 == 'POP_BLOCK':
246-
pop_block()
247+
last_block = pop_block()
247248
elif opname1 == 'POP_EXCEPT':
248-
pop_block_of_type('<EXCEPT>')
249+
last_block = pop_block_of_type('<EXCEPT>')
249250
elif opname1 == 'END_FINALLY':
250251
if opname0 != 'JUMP_FORWARD': # hack for dummy end-finally in except block (correct fix would be a jump-aware reading of instructions!)
251-
pop_block_of_type('<FINALLY>')
252-
elif opname1 in ('WITH_CLEANUP', 'WITH_CLEANUP_START') and _BYTECODE.has_setup_with:
253-
block_stack.append(('<FINALLY>', -1)) # temporary block to match END_FINALLY
252+
last_block = pop_block_of_type('<FINALLY>')
253+
elif opname1 in ('WITH_CLEANUP', 'WITH_CLEANUP_START'):
254+
if _BYTECODE.has_setup_with:
255+
block_stack.append(('<FINALLY>', -1)) # temporary block to match END_FINALLY
256+
else:
257+
replace_block(last_block, ('SETUP_WITH',) + last_block[1:]) # python 2.6 - finally was actually with
254258

255259
opname0, oparg0, offset0 = opname1, oparg1, offset1
256260
opname1, oparg1, offset1 = opname2, oparg2, offset2

test_goto.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,39 @@ def func():
166166

167167
assert func() == (1, 0, 0, 0, 0)
168168

169+
def test_large_jumps_in_diff_orders():
170+
@with_goto
171+
def func():
172+
goto .start
173+
174+
if NonConstFalse:
175+
label .finalle
176+
return (i, j, k, m, n, i1, j1, k1, m1, n1, i2, j2, k2, m2, n2)
177+
178+
label .start
179+
for i in range(2):
180+
for j in range(2):
181+
for k in range(2):
182+
for m in range(2):
183+
for n in range(2):
184+
goto .end
185+
label .end
186+
for i1 in range(2):
187+
for j1 in range(2):
188+
for k1 in range(2):
189+
for m1 in range(2):
190+
for n1 in range(2):
191+
goto .end2
192+
label .end2
193+
for i2 in range(2):
194+
for j2 in range(2):
195+
for k2 in range(2):
196+
for m2 in range(2):
197+
for n2 in range(2):
198+
goto .finalle
199+
200+
assert func() == (0,) * 15
201+
169202
def test_jump_out_of_nested_11_loops():
170203
@with_goto
171204
def func():
@@ -225,6 +258,18 @@ def func():
225258

226259
assert func()== (1, 0)
227260

261+
def test_jump_out_of_with_block_and_survive():
262+
@with_goto
263+
def func():
264+
c = Context()
265+
for i in range(3):
266+
with c:
267+
goto .out
268+
label .out
269+
return (i, c.data())
270+
271+
assert func() == (2, (3, 0))
272+
228273
def test_jump_out_of_with_block_and_live():
229274
@with_goto
230275
def func():

0 commit comments

Comments
 (0)