Python 2.6- try/except control flow detection

This commit is contained in:
rocky
2016-09-05 04:02:37 -04:00
parent c7788e4545
commit 318311818e
6 changed files with 26 additions and 20 deletions

View File

@@ -181,6 +181,11 @@ class Python2Parser(PythonParser):
trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK trystmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
try_middle COME_FROM try_middle COME_FROM
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY COME_FROM
try_middle ::= jmp_abs COME_FROM except_stmts
END_FINALLY
except_stmts ::= except_stmts except_stmt except_stmts ::= except_stmts except_stmt
except_stmts ::= except_stmt except_stmts ::= except_stmt

View File

@@ -27,11 +27,7 @@ class Python26Parser(Python2Parser):
POP_TOP END_FINALLY come_froms POP_TOP END_FINALLY come_froms
try_middle ::= JUMP_FORWARD COME_FROM except_stmts try_middle ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY come_froms come_from_pop END_FINALLY COME_FROM
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
come_from_pop END_FINALLY come_froms
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY come_froms
try_middle ::= jmp_abs COME_FROM except_stmts try_middle ::= jmp_abs COME_FROM except_stmts
POP_TOP END_FINALLY POP_TOP END_FINALLY
@@ -39,9 +35,6 @@ class Python26Parser(Python2Parser):
try_middle ::= jmp_abs COME_FROM except_stmts try_middle ::= jmp_abs COME_FROM except_stmts
come_from_pop END_FINALLY come_from_pop END_FINALLY
try_middle ::= jmp_abs COME_FROM except_stmts
END_FINALLY
trystmt ::= SETUP_EXCEPT suite_stmts_opt come_from_pop trystmt ::= SETUP_EXCEPT suite_stmts_opt come_from_pop
try_middle try_middle

View File

@@ -27,11 +27,6 @@ class Python27Parser(Python2Parser):
def p_try27(self, args): def p_try27(self, args):
""" """
try_middle ::= JUMP_FORWARD COME_FROM except_stmts
END_FINALLY COME_FROM
try_middle ::= jmp_abs COME_FROM except_stmts
END_FINALLY
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
try_middle else_suite COME_FROM try_middle else_suite COME_FROM

View File

@@ -44,7 +44,7 @@ class Scanner2(scan.Scanner):
Pick out tokens from an uncompyle6 code object, and transform them, Pick out tokens from an uncompyle6 code object, and transform them,
returning a list of uncompyle6 'Token's. returning a list of uncompyle6 'Token's.
The tranformations are made to assist the deparsing grammar. The transformations are made to assist the deparsing grammar.
Specificially: Specificially:
- various types of LOAD_CONST's are categorized in terms of what they load - various types of LOAD_CONST's are categorized in terms of what they load
- COME_FROM instructions are added to assist parsing control structures - COME_FROM instructions are added to assist parsing control structures
@@ -56,7 +56,7 @@ class Scanner2(scan.Scanner):
""" """
show_asm = self.show_asm if not show_asm else show_asm show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'both' # show_asm = 'after'
if show_asm in ('both', 'before'): if show_asm in ('both', 'before'):
from xdis.bytecode import Bytecode from xdis.bytecode import Bytecode
bytecode = Bytecode(co, self.opc) bytecode = Bytecode(co, self.opc)
@@ -846,6 +846,8 @@ class Scanner2(scan.Scanner):
pass pass
pass pass
# FIXME: All the <2.6 conditions are is horrible. We need a better way.
if label is not None and label != -1: if label is not None and label != -1:
# In Python <= 2.6, the POP_TOP in: # In Python <= 2.6, the POP_TOP in:
# RETURN_VALUE, POP_TOP # RETURN_VALUE, POP_TOP
@@ -854,8 +856,19 @@ class Scanner2(scan.Scanner):
if not (self.version <= 2.6 and if not (self.version <= 2.6 and
self.code[label] == self.opc.POP_TOP and self.code[label] == self.opc.POP_TOP and
self.code[self.prev[label]] == self.opc.RETURN_VALUE): self.code[self.prev[label]] == self.opc.RETURN_VALUE):
targets[label] = targets.get(label, []) + [offset] # In Python <= 2.6, don't add a COME_FROM, for:
elif op == self.opc.END_FINALLY and offset in self.fixed_jumps: # JUMP_FORWARD, END_FINALLY
# or:
# JUMP_FORWARD, POP_TOP, END_FINALLY
if not (self.version <= 2.6 and op == self.opc.JUMP_FORWARD
and ((self.code[offset+3] == self.opc.END_FINALLY)
or (self.code[offset+3] == self.opc.POP_TOP
and self.code[offset+4] == self.opc.END_FINALLY))):
targets[label] = targets.get(label, []) + [offset]
pass
pass
pass
elif op == self.opc.END_FINALLY and offset in self.fixed_jumps and self.version == 2.7:
label = self.fixed_jumps[offset] label = self.fixed_jumps[offset]
targets[label] = targets.get(label, []) + [offset] targets[label] = targets.get(label, []) + [offset]
return targets return targets

View File

@@ -75,7 +75,7 @@ class Scanner26(scan.Scanner2):
Pick out tokens from an uncompyle6 code object, and transform them, Pick out tokens from an uncompyle6 code object, and transform them,
returning a list of uncompyle6 'Token's. returning a list of uncompyle6 'Token's.
The tranformations are made to assist the deparsing grammar. The transformations are made to assist the deparsing grammar.
Specificially: Specificially:
- various types of LOAD_CONST's are categorized in terms of what they load - various types of LOAD_CONST's are categorized in terms of what they load
- COME_FROM instructions are added to assist parsing control structures - COME_FROM instructions are added to assist parsing control structures
@@ -87,7 +87,7 @@ class Scanner26(scan.Scanner2):
""" """
show_asm = self.show_asm if not show_asm else show_asm show_asm = self.show_asm if not show_asm else show_asm
# show_asm = 'both' # show_asm = 'after'
if show_asm in ('both', 'before'): if show_asm in ('both', 'before'):
from xdis.bytecode import Bytecode from xdis.bytecode import Bytecode
bytecode = Bytecode(co, self.opc) bytecode = Bytecode(co, self.opc)

View File

@@ -115,7 +115,7 @@ class Scanner3(Scanner):
Pick out tokens from an uncompyle6 code object, and transform them, Pick out tokens from an uncompyle6 code object, and transform them,
returning a list of uncompyle6 'Token's. returning a list of uncompyle6 'Token's.
The tranformations are made to assist the deparsing grammar. The transformations are made to assist the deparsing grammar.
Specificially: Specificially:
- various types of LOAD_CONST's are categorized in terms of what they load - various types of LOAD_CONST's are categorized in terms of what they load
- COME_FROM instructions are added to assist parsing control structures - COME_FROM instructions are added to assist parsing control structures