Fix 3.5+ bug in if's with pass bodies

Fixes #104 in a somewhat hacky way.
This commit is contained in:
rocky 2018-01-08 10:21:53 -05:00
parent fbda3ca695
commit f59174575e
6 changed files with 32 additions and 15 deletions

View File

@ -66,6 +66,9 @@ def test_if_in_for():
scan.build_lines_data(code)
scan.build_prev_op()
scan.insts = list(bytecode)
scan.offset2inst_index = {}
for i, inst in enumerate(scan.insts):
scan.offset2inst_index[inst.offset] = i
fjt = scan.find_jump_targets(False)
assert {69: [66], 63: [18]} == fjt
assert scan.structs == \

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,9 @@
# Issue 104 seen in Python 3.5
# Since we have empty statement bodies the if's can get confused
# with "and/or". There is a lot of flakiness in control flow here,
# and this needs to be straightened out in a more uniform way
if __file__:
if __name__:
pass
elif __import__:
pass

View File

@ -1,4 +1,4 @@
# Copyright (c) 2015-2017 by Rocky Bernstein
# Copyright (c) 2015-2018 by Rocky Bernstein
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
"""
@ -767,18 +767,25 @@ class Scanner3(Scanner):
# not myself? If so, it's part of a larger conditional.
# rocky: if we have a conditional jump to the next instruction, then
# possibly I am "skipping over" a "pass" or null statement.
pretarget = self.insts[self.offset2inst_index[prev_op[target]]]
if ((code[prev_op[target]] in self.pop_jump_if_pop) and
(target > offset) and prev_op[target] != offset):
# FIXME: this is not accurate The commented out below
# is what it should be. However grammar rules right now
# assume the incorrect offsets.
# self.fixed_jumps[offset] = target
self.fixed_jumps[offset] = prev_op[target]
self.structs.append({'type': 'and/or',
'start': start,
'end': prev_op[target]})
return
if (pretarget.opcode in self.pop_jump_if_pop and
(target > offset) and pretarget.offset != offset):
# FIXME: hack upon hack...
# In some cases the pretarget can be a jump to the next instruction
# and these aren't and/or's either. We limit to 3.5+ since we experienced there
# but it might be earlier versions, or might be a general principle.
if self.version < 3.5 or pretarget.argval != target:
# FIXME: this is not accurate The commented out below
# is what it should be. However grammar rules right now
# assume the incorrect offsets.
# self.fixed_jumps[offset] = target
self.fixed_jumps[offset] = pretarget.offset
self.structs.append({'type': 'and/or',
'start': start,
'end': pretarget.offset})
return
# The opcode *two* instructions before the target jump offset is important
# in making a determination of what we have. Save that.

View File

@ -1,4 +1,4 @@
# Copyright (c) 2016-2017 by Rocky Bernstein
# Copyright (c) 2016-2018 by Rocky Bernstein
"""
Python 3.6 bytecode decompiler scanner
@ -13,8 +13,6 @@ from __future__ import print_function
from uncompyle6.scanners.scanner3 import Scanner3
import xdis
# bytecode verification, verify(), uses JUMP_OPS from here
from xdis.opcodes import opcode_36 as opc
JUMP_OPS = opc.JUMP_OPS