More 2.6, 2.7 control-flow bugs

Wasn't limiting exception clause to try finally. Probably still has bugs
in try-finally nesting

Add another 2.6/2.7 COME_FROM to try to limit if/end scope better
This commit is contained in:
rocky
2017-01-24 00:53:30 -05:00
parent 597d51951e
commit 9ec312ba5e
5 changed files with 30 additions and 9 deletions

View File

@@ -126,6 +126,7 @@ class Python2Parser(PythonParser):
assert_expr_and ::= assert_expr jmp_false expr
ifstmt ::= testexpr _ifstmts_jump
ifstmt ::= testexpr return_if_stmts COME_FROM
testexpr ::= testfalse
testexpr ::= testtrue
@@ -144,6 +145,8 @@ class Python2Parser(PythonParser):
ifelsestmtr ::= testexpr return_if_stmts return_stmts
ifelsestmtr ::= testexpr return_if_stmts COME_FROM return_stmts
ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel

View File

@@ -61,7 +61,7 @@ class Python27Parser(Python2Parser):
ret_and ::= expr JUMP_IF_FALSE_OR_POP ret_expr_or_cond COME_FROM
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF ret_expr_or_cond
ret_cond ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
ret_cond_not ::= expr POP_JUMP_IF_TRUE expr RETURN_END_IF ret_expr_or_cond
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM

View File

@@ -630,9 +630,16 @@ class Scanner2(scan.Scanner):
# Now isolate the except and else blocks
end_else = start_else = self.get_target(self.prev[end])
end_finally_offset = end
while end_finally_offset < len(self.code):
if self.code[end_finally_offset] == self.opc.END_FINALLY:
break
end_finally_offset += self.op_size(code[end_finally_offset])
# Add the except blocks
i = end
while i < len(self.code) and self.code[i] != self.opc.END_FINALLY:
while i < len(self.code) and i < end_finally_offset:
jmp = self.next_except_jump(i)
if jmp is None: # check
i = self.next_stmt[i]
@@ -924,6 +931,7 @@ class Scanner2(scan.Scanner):
'end': rtarget})
self.thens[start] = rtarget
if self.version == 2.7 or code[pre_rtarget+1] != self.opc.JUMP_FORWARD:
self.fixed_jumps[offset] = rtarget
self.return_end_ifs.add(pre_rtarget)
elif op in self.pop_jump_if_or_pop:

View File

@@ -223,6 +223,7 @@ TABLE_DIRECT = {
'elifstmt': ( '%|elif %c:\n%+%c%-', 0, 1 ),
'elifelsestmt': ( '%|elif %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 3 ),
'ifelsestmtr': ( '%|if %c:\n%+%c%-%|else:\n%+%c%-', 0, 1, 2 ),
'ifelsestmtr2': ( '%|if %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 3 ), # has COME_FROM
'elifelsestmtr': ( '%|elif %c:\n%+%c%-%|else:\n%+%c%-\n\n', 0, 1, 2 ),
'whileTruestmt': ( '%|while True:\n%+%c%-\n\n', 1 ),

View File

@@ -723,11 +723,18 @@ class SourceWalker(GenericASTTraversal, object):
n_ifelsestmtc = n_ifelsestmtl = n_ifelsestmt
def n_ifelsestmtr(self, node):
if len(node[2]) != 2:
if node[2] == 'COME_FROM':
return_stmts_node = node[3]
node.type = 'ifelsestmtr2'
else:
return_stmts_node = node[2]
if len(return_stmts_node) != 2:
self.default(node)
if not (node[2][0][0][0] == 'ifstmt' and node[2][0][0][0][1][0] == 'return_if_stmts') \
and not (node[2][0][-1][0] == 'ifstmt' and node[2][0][-1][0][1][0] == 'return_if_stmts'):
if (not (return_stmts_node[0][0][0] == 'ifstmt'
and return_stmts_node[0][0][0][1][0] == 'return_if_stmts')
and not (return_stmts_node[0][-1][0] == 'ifstmt'
and return_stmts_node[0][-1][0][1][0] == 'return_if_stmts')):
self.default(node)
return
@@ -739,13 +746,14 @@ class SourceWalker(GenericASTTraversal, object):
self.indentLess()
if_ret_at_end = False
if len(node[2][0]) >= 3:
if node[2][0][-1][0] == 'ifstmt' and node[2][0][-1][0][1][0] == 'return_if_stmts':
if len(return_stmts_node[0]) >= 3:
if (return_stmts_node[0][-1][0] == 'ifstmt'
and return_stmts_node[0][-1][0][1][0] == 'return_if_stmts'):
if_ret_at_end = True
past_else = False
prev_stmt_is_if_ret = True
for n in node[2][0]:
for n in return_stmts_node[0]:
if (n[0] == 'ifstmt' and n[0][1][0] == 'return_if_stmts'):
if prev_stmt_is_if_ret:
n[0].type = 'elifstmt'
@@ -760,9 +768,10 @@ class SourceWalker(GenericASTTraversal, object):
if not past_else or if_ret_at_end:
self.println(self.indent, 'else:')
self.indentMore()
self.preorder(node[2][1])
self.preorder(return_stmts_node[1])
self.indentLess()
self.prune()
n_ifelsestmtr2 = n_ifelsestmtr
def n_elifelsestmtr(self, node):
if len(node[2]) != 2: