mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2024-10-07 10:13:39 +00:00
Fix 3.5+ bug in if's with pass bodies
Fixes #104 in a somewhat hacky way.
This commit is contained in:
parent
fbda3ca695
commit
f59174575e
@ -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 == \
|
||||
|
BIN
test/bytecode_3.5/05_empty_ifs.pyc
Normal file
BIN
test/bytecode_3.5/05_empty_ifs.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_3.6/05_empty_ifs.pyc
Normal file
BIN
test/bytecode_3.6/05_empty_ifs.pyc
Normal file
Binary file not shown.
9
test/simple_source/bug35/05_empty_ifs.py
Normal file
9
test/simple_source/bug35/05_empty_ifs.py
Normal 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
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user