Python 3.6 control flow bug...

Much more is needed, but it's a start
This commit is contained in:
rocky
2017-10-29 23:52:58 -04:00
parent 95268cb14e
commit b83d6c64ed
4 changed files with 66 additions and 4 deletions

Binary file not shown.

View File

@@ -0,0 +1,49 @@
# Bug in 3.6 has to do with parsing jumps where
# the offset is more than 256 bytes so an EXTENDED_ARG
# instruction is inserted. find_jump_targets() and
# detect_control_flow need to be able to work in the presence
# of EXTENDED_ARG.
# This is a problem theoretically in Python before 3.6
# but since offsets are very large it isn't noticed.
# Code is simplified from trepan2/trepan/cli.py
import sys
def main(dbg=None, sys_argv=list(sys.argv)):
if sys_argv:
mainpyfile = None
else:
mainpyfile = "10"
sys.path[0] = "20"
while True:
try:
if dbg.program_sys_argv and mainpyfile:
normal_termination = dbg.run_script(mainpyfile)
if not normal_termination: break
else:
dbg.core.execution_status = 'No program'
dbg.core.processor.process_commands()
pass
dbg.core.execution_status = 'Terminated'
dbg.intf[-1].msg("The program finished - quit or restart")
dbg.core.processor.process_commands()
except IOError:
break
except RuntimeError:
dbg.core.execution_status = 'Restart requested'
if dbg.program_sys_argv:
sys.argv = list(dbg.program_sys_argv)
part1 = ('Restarting %s with arguments:' %
dbg.core.filename(mainpyfile))
args = ' '.join(dbg.program_sys_argv[1:])
dbg.intf[-1].msg(args + part1)
else: break
except SystemExit:
break
pass
sys.argv = 5
return

View File

@@ -32,6 +32,11 @@ class Python36Parser(Python35Parser):
call_function ::= expr expr CALL_FUNCTION_EX
call_function ::= expr expr expr CALL_FUNCTION_EX_KW_1
# This might be valid in < 3.6
and ::= expr jmp_false expr
except_suite ::= c_stmts_opt COME_FROM POP_EXCEPT jump_except COME_FROM
"""
def add_custom_rules(self, tokens, customize):

View File

@@ -213,7 +213,7 @@ class Scanner3(Scanner):
# Get jump targets
# Format: {target offset: [jump offsets]}
jump_targets = self.find_jump_targets(show_asm)
## print("XXX2", jump_targets)
# print("XXX2", jump_targets)
last_op_was_break = False
extended_arg = 0
@@ -797,7 +797,7 @@ class Scanner3(Scanner):
'end': prev_op[target]})
return
# The op offset just before the target jump offset is important
# The opcode *two* instructions before the target jump offset is important
# in making a determination of what we have. Save that.
pre_rtarget = prev_op[rtarget]
@@ -966,8 +966,16 @@ class Scanner3(Scanner):
self.not_continue.add(pre_rtarget)
else:
# For now, we'll only tag forward jump.
if rtarget > offset:
self.fixed_jumps[offset] = rtarget
if self.version >= 3.6:
if target > offset:
self.fixed_jumps[offset] = target
pass
else:
# FIXME: This is probably a bug in < 3.6 and we should
# instead use the above code. But until we smoke things
# out we'll stick with it.
if rtarget > offset:
self.fixed_jumps[offset] = rtarget
elif op == self.opc.SETUP_EXCEPT:
target = self.get_target(offset, extended_arg)