You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 09:22:40 +08:00
EXTENDED_ARG handling...
get_target() wasn't taking into account EXTENDED_ARG before opcode. This is mostly relevant in Python 3.6 where the max size before needing EXTENDED_ARG has been reduced to 256, but theoretically possible in earlier versions.
This commit is contained in:
@@ -61,6 +61,8 @@ class Python36Parser(Python35Parser):
|
|||||||
continue_stmt ::= EXTENDED_ARG CONTINUE_LOOP
|
continue_stmt ::= EXTENDED_ARG CONTINUE_LOOP
|
||||||
|
|
||||||
for_block ::= l_stmts_opt opt_come_from_loop jump_back
|
for_block ::= l_stmts_opt opt_come_from_loop jump_back
|
||||||
|
cmp_list1 ::= expr DUP_TOP ROT_THREE COMPARE_OP
|
||||||
|
EXTENDED_ARG JUMP_IF_FALSE_OR_POP cmp_list2 COME_FROM
|
||||||
|
|
||||||
|
|
||||||
# 3.6 redoes how return_closure works
|
# 3.6 redoes how return_closure works
|
||||||
|
@@ -27,6 +27,7 @@ from array import array
|
|||||||
|
|
||||||
from uncompyle6.scanner import Scanner, op_has_argument
|
from uncompyle6.scanner import Scanner, op_has_argument
|
||||||
from xdis.code import iscode
|
from xdis.code import iscode
|
||||||
|
from xdis.util import code2num
|
||||||
from xdis.bytecode import Bytecode
|
from xdis.bytecode import Bytecode
|
||||||
from uncompyle6.scanner import Token, parse_fn_counts
|
from uncompyle6.scanner import Token, parse_fn_counts
|
||||||
|
|
||||||
@@ -603,15 +604,27 @@ class Scanner3(Scanner):
|
|||||||
Get target offset for op located at given <offset>.
|
Get target offset for op located at given <offset>.
|
||||||
"""
|
"""
|
||||||
op = self.code[offset]
|
op = self.code[offset]
|
||||||
|
rel_offset = 0
|
||||||
if self.version >= 3.6:
|
if self.version >= 3.6:
|
||||||
target = self.code[offset+1]
|
target = self.code[offset+1]
|
||||||
|
arg_offset = 1
|
||||||
|
extended_arg_mult = 1 << 8
|
||||||
if op in self.opc.hasjrel:
|
if op in self.opc.hasjrel:
|
||||||
target += offset + 2
|
rel_offset = offset + 2
|
||||||
else:
|
else:
|
||||||
target = self.code[offset+1] + self.code[offset+2] * 256
|
target = self.code[offset+1] + self.code[offset+2] * 256
|
||||||
|
arg_offset = 2
|
||||||
|
extended_arg_mult = 1 << 16
|
||||||
if op in self.opc.hasjrel:
|
if op in self.opc.hasjrel:
|
||||||
target += offset + 3
|
rel_offset = offset + 3
|
||||||
|
pass
|
||||||
|
pass
|
||||||
|
target += rel_offset
|
||||||
|
prev_offset = self.prev_op[offset]
|
||||||
|
prev_op = code2num(self.code, prev_offset)
|
||||||
|
if prev_op == self.opc.EXTENDED_ARG:
|
||||||
|
target += (code2num(self.code, prev_offset + arg_offset) * extended_arg_mult)
|
||||||
|
pass
|
||||||
return target
|
return target
|
||||||
|
|
||||||
def detect_control_flow(self, offset, targets):
|
def detect_control_flow(self, offset, targets):
|
||||||
@@ -755,7 +768,7 @@ class Scanner3(Scanner):
|
|||||||
pre_rtarget = prev_op[rtarget]
|
pre_rtarget = prev_op[rtarget]
|
||||||
|
|
||||||
# Is it an "and" inside an "if" or "while" block
|
# Is it an "and" inside an "if" or "while" block
|
||||||
if op == self.opc.POP_JUMP_IF_FALSE:
|
if op == self.opc.POP_JUMP_IF_FALSE and self.version < 3.6:
|
||||||
|
|
||||||
# Search for another POP_JUMP_IF_FALSE targetting the same op,
|
# Search for another POP_JUMP_IF_FALSE targetting the same op,
|
||||||
# in current statement, starting from current offset, and filter
|
# in current statement, starting from current offset, and filter
|
||||||
|
Reference in New Issue
Block a user