python-uncompyle6
python-uncompyle6 copied to clipboard
`JUMP_ABSOLUTE` decompilation error
Description
Like in #310, I am running against a JUMP_ABSOLUTE error with a piece of bytecode written in Python 2.7, using uncompyle6 3.9.0a1 (source code from GitHub, current master branch):
class Test:
elements = []
def test--- This code section failed: ---
L. 4 0 SETUP_LOOP 61 'to 64'
3 LOAD_GLOBAL 0 'Test'
6 LOAD_ATTR 1 'elements'
9 GET_ITER
10 FOR_ITER 50 'to 63'
13 STORE_FAST 1 'element'
L. 5 16 LOAD_FAST 1 'element'
19 LOAD_ATTR 2 'a'
22 POP_JUMP_IF_FALSE 10 'to 10'
L. 6 25 LOAD_FAST 1 'element'
28 LOAD_ATTR 3 'b'
31_0 COME_FROM 22 '22'
31 POP_JUMP_IF_FALSE 10 'to 10'
L. 7 34 JUMP_FORWARD 3 'to 40'
L. 9 37 CONTINUE 10 'to 10'
40_0 COME_FROM 34 '34'
L. 10 40 LOAD_FAST 1 'element'
43 LOAD_ATTR 4 'c'
46 POP_JUMP_IF_FALSE 60 'to 60'
L. 11 49 LOAD_GLOBAL 5 'Hello'
52 PRINT_ITEM
53 PRINT_NEWLINE_CONT
54 JUMP_ABSOLUTE 60 'to 60'
57 JUMP_BACK 10 'to 10'
60 JUMP_BACK 10 'to 10'
63 POP_BLOCK
64_0 COME_FROM 0 '0'
Parse error at or near `JUMP_ABSOLUTE' instruction at offset 54
How to Reproduce
Code
class Test():
elements = []
def test(self):
for element in Test.elements:
if element.a:
if element.b:
pass
else:
continue
if element.c:
print Hello
Output Given
Output
# uncompyle6 version 3.9.0a1
# Python bytecode version base 2.7 (62211)
# Decompiled from: Python 3.9.2 (default, Feb 28 2021, 17:03:44)
# [GCC 10.2.1 20210110]
# Embedded file name: ./test.3.py
# Compiled at: 2022-09-20 22:47:05
-- Stacks of completed symbols:
START ::= |- stmts .
_come_froms ::= \e__come_froms . COME_FROM
_ifstmts_jump ::= \e_c_stmts_opt . JUMP_FORWARD come_froms
_ifstmts_jump ::= \e_c_stmts_opt JUMP_FORWARD . come_froms
_ifstmts_jump ::= c_stmts_opt . JUMP_FORWARD come_froms
_stmts ::= _stmts . stmt
_stmts ::= stmt .
and ::= expr . JUMP_IF_FALSE_OR_POP expr COME_FROM
and ::= expr . jmp_false expr \e_come_from_opt
and ::= expr . jmp_false expr come_from_opt
and ::= expr jmp_false . expr \e_come_from_opt
and ::= expr jmp_false . expr come_from_opt
and ::= expr jmp_false expr . come_from_opt
and ::= expr jmp_false expr \e_come_from_opt .
and ::= expr jmp_false expr come_from_opt .
assert ::= assert_expr . jmp_true LOAD_ASSERT RAISE_VARARGS_1
assert2 ::= assert_expr . jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
assert_expr ::= assert_expr_and .
assert_expr ::= expr .
assert_expr_and ::= assert_expr . jmp_false expr
assert_expr_and ::= assert_expr jmp_false . expr
assert_expr_and ::= assert_expr jmp_false expr .
assert_expr_or ::= assert_expr . jmp_true expr
assign ::= expr . DUP_TOP designList
assign ::= expr . store
assign2 ::= expr . expr ROT_TWO store store
assign3 ::= expr . expr expr ROT_THREE ROT_TWO store store store
attribute ::= expr . GET_ITER
attribute ::= expr . LOAD_ATTR
attribute ::= expr GET_ITER .
attribute ::= expr LOAD_ATTR .
aug_assign1 ::= expr . expr inplace_op ROT_FOUR STORE_SLICE+3
aug_assign1 ::= expr . expr inplace_op ROT_THREE STORE_SLICE+1
aug_assign1 ::= expr . expr inplace_op ROT_THREE STORE_SLICE+2
aug_assign1 ::= expr . expr inplace_op ROT_THREE STORE_SUBSCR
aug_assign1 ::= expr . expr inplace_op ROT_TWO STORE_SLICE+0
aug_assign1 ::= expr . expr inplace_op store
aug_assign2 ::= expr . DUP_TOP LOAD_ATTR expr inplace_op ROT_TWO STORE_ATTR
bin_op ::= expr . expr binary_operator
c_stmts ::= _stmts .
c_stmts ::= _stmts . lastc_stmt
c_stmts_opt ::= c_stmts .
call ::= expr . CALL_FUNCTION_0
call_stmt ::= expr . POP_TOP
classdefdeco1 ::= expr . classdefdeco1 CALL_FUNCTION_1
classdefdeco1 ::= expr . classdefdeco2 CALL_FUNCTION_1
come_from_opt ::= COME_FROM .
come_froms ::= COME_FROM .
come_froms ::= come_froms . COME_FROM
compare_chained ::= expr . compare_chained1 ROT_TWO POP_TOP \e__come_froms
compare_chained ::= expr . compare_chained1 ROT_TWO POP_TOP _come_froms
compare_single ::= expr . expr COMPARE_OP
continue ::= CONTINUE .
continues ::= _stmts . lastl_stmt continue
continues ::= _stmts lastl_stmt . continue
continues ::= continue .
delete ::= expr . DELETE_ATTR
delete_subscript ::= expr . expr DELETE_SUBSCR
else_suite ::= suite_stmts .
expr ::= LOAD_FAST .
expr ::= LOAD_GLOBAL .
expr ::= and .
expr ::= attribute .
expr ::= get_iter .
expr_jitop ::= expr . JUMP_IF_TRUE_OR_POP
expr_jt ::= expr . jmp_true
for ::= SETUP_LOOP . expr for_iter store for_block POP_BLOCK \e__come_froms
for ::= SETUP_LOOP . expr for_iter store for_block POP_BLOCK _come_froms
for ::= SETUP_LOOP expr . for_iter store for_block POP_BLOCK \e__come_froms
for ::= SETUP_LOOP expr . for_iter store for_block POP_BLOCK _come_froms
for ::= SETUP_LOOP expr for_iter . store for_block POP_BLOCK \e__come_froms
for ::= SETUP_LOOP expr for_iter . store for_block POP_BLOCK _come_froms
for ::= SETUP_LOOP expr for_iter store . for_block POP_BLOCK \e__come_froms
for ::= SETUP_LOOP expr for_iter store . for_block POP_BLOCK _come_froms
for_block ::= \e_l_stmts_opt . JUMP_BACK
for_block ::= \e_l_stmts_opt . _come_froms JUMP_BACK
for_block ::= \e_l_stmts_opt \e__come_froms . JUMP_BACK
for_block ::= l_stmts_opt . JUMP_BACK
for_block ::= l_stmts_opt . _come_froms JUMP_BACK
for_block ::= l_stmts_opt \e__come_froms . JUMP_BACK
for_iter ::= GET_ITER . COME_FROM FOR_ITER
for_iter ::= GET_ITER . FOR_ITER
for_iter ::= GET_ITER FOR_ITER .
forelsestmt ::= SETUP_LOOP . expr for_iter store for_block POP_BLOCK else_suite \e__come_froms
forelsestmt ::= SETUP_LOOP . expr for_iter store for_block POP_BLOCK else_suite _come_froms
forelsestmt ::= SETUP_LOOP expr . for_iter store for_block POP_BLOCK else_suite \e__come_froms
forelsestmt ::= SETUP_LOOP expr . for_iter store for_block POP_BLOCK else_suite _come_froms
forelsestmt ::= SETUP_LOOP expr for_iter . store for_block POP_BLOCK else_suite \e__come_froms
forelsestmt ::= SETUP_LOOP expr for_iter . store for_block POP_BLOCK else_suite _come_froms
forelsestmt ::= SETUP_LOOP expr for_iter store . for_block POP_BLOCK else_suite \e__come_froms
forelsestmt ::= SETUP_LOOP expr for_iter store . for_block POP_BLOCK else_suite _come_froms
genexpr_func ::= LOAD_FAST . FOR_ITER store comp_iter JUMP_BACK
get_iter ::= expr . GET_ITER
get_iter ::= expr GET_ITER .
if_exp ::= expr . jmp_false expr JUMP_ABSOLUTE expr
if_exp ::= expr . jmp_false expr JUMP_FORWARD expr COME_FROM
if_exp ::= expr jmp_false . expr JUMP_ABSOLUTE expr
if_exp ::= expr jmp_false . expr JUMP_FORWARD expr COME_FROM
if_exp ::= expr jmp_false expr . JUMP_ABSOLUTE expr
if_exp ::= expr jmp_false expr . JUMP_FORWARD expr COME_FROM
if_exp_lambda ::= expr . jmp_false expr return_if_lambda return_stmt_lambda LAMBDA_MARKER
if_exp_lambda ::= expr jmp_false . expr return_if_lambda return_stmt_lambda LAMBDA_MARKER
if_exp_lambda ::= expr jmp_false expr . return_if_lambda return_stmt_lambda LAMBDA_MARKER
if_exp_not ::= expr . jmp_true expr _jump expr COME_FROM
if_exp_not_lambda ::= expr . jmp_true expr return_if_lambda return_stmt_lambda LAMBDA_MARKER
if_exp_true ::= expr . JUMP_FORWARD expr COME_FROM
ifelsestmt ::= testexpr . c_stmts_opt JUMP_FORWARD else_suite come_froms
ifelsestmt ::= testexpr \e_c_stmts_opt . JUMP_FORWARD else_suite come_froms
ifelsestmt ::= testexpr \e_c_stmts_opt JUMP_FORWARD . else_suite come_froms
ifelsestmt ::= testexpr \e_c_stmts_opt JUMP_FORWARD else_suite . come_froms
ifelsestmt ::= testexpr \e_c_stmts_opt JUMP_FORWARD else_suite come_froms .
ifelsestmt ::= testexpr c_stmts_opt . JUMP_FORWARD else_suite come_froms
ifelsestmtl ::= testexpr . c_stmts_opt CONTINUE else_suitel
ifelsestmtl ::= testexpr . c_stmts_opt JUMP_BACK else_suitel
ifelsestmtl ::= testexpr \e_c_stmts_opt . CONTINUE else_suitel
ifelsestmtl ::= testexpr \e_c_stmts_opt . JUMP_BACK else_suitel
ifelsestmtl ::= testexpr c_stmts_opt . CONTINUE else_suitel
ifelsestmtl ::= testexpr c_stmts_opt . JUMP_BACK else_suitel
ifelsestmtr ::= testexpr . return_if_stmts COME_FROM returns
iflaststmtl ::= testexpr . c_stmts
iflaststmtl ::= testexpr . c_stmts_opt JUMP_BACK
iflaststmtl ::= testexpr \e_c_stmts_opt . JUMP_BACK
iflaststmtl ::= testexpr c_stmts .
iflaststmtl ::= testexpr c_stmts_opt . JUMP_BACK
ifstmt ::= testexpr . _ifstmts_jump
ifstmt ::= testexpr . return_if_stmts COME_FROM
ifstmt ::= testexpr . return_stmts COME_FROM
jmp_false ::= POP_JUMP_IF_FALSE .
l_stmts ::= _stmts .
l_stmts ::= _stmts . lastl_stmt
l_stmts ::= _stmts lastl_stmt .
l_stmts_opt ::= l_stmts .
lastl_stmt ::= iflaststmtl .
mkfuncdeco ::= expr . mkfuncdeco CALL_FUNCTION_1
mkfuncdeco ::= expr . mkfuncdeco0 CALL_FUNCTION_1
print_items_nl_stmt ::= expr . PRINT_ITEM \e_print_items_opt PRINT_NEWLINE_CONT
print_items_nl_stmt ::= expr . PRINT_ITEM print_items_opt PRINT_NEWLINE_CONT
print_items_nl_stmt ::= expr PRINT_ITEM . print_items_opt PRINT_NEWLINE_CONT
print_items_nl_stmt ::= expr PRINT_ITEM \e_print_items_opt . PRINT_NEWLINE_CONT
print_items_nl_stmt ::= expr PRINT_ITEM \e_print_items_opt PRINT_NEWLINE_CONT .
print_items_stmt ::= expr . PRINT_ITEM \e_print_items_opt
print_items_stmt ::= expr . PRINT_ITEM print_items_opt
print_items_stmt ::= expr PRINT_ITEM . print_items_opt
print_items_stmt ::= expr PRINT_ITEM \e_print_items_opt .
print_nl_to ::= expr . PRINT_NEWLINE_TO
print_to ::= expr . print_to_items POP_TOP
print_to_nl ::= expr . print_to_items PRINT_NEWLINE_TO
raise_stmt1 ::= expr . RAISE_VARARGS_1
raise_stmt2 ::= expr . expr RAISE_VARARGS_2
raise_stmt3 ::= expr . expr expr RAISE_VARARGS_3
ret_and ::= expr . JUMP_IF_FALSE_OR_POP return_expr_or_cond COME_FROM
ret_or ::= expr . JUMP_IF_TRUE_OR_POP return_expr_or_cond COME_FROM
return ::= return_expr . RETURN_VALUE
return_expr ::= expr .
return_expr_lambda ::= return_expr . RETURN_VALUE_LAMBDA
return_expr_lambda ::= return_expr . RETURN_VALUE_LAMBDA LAMBDA_MARKER
return_if_stmt ::= return_expr . RETURN_END_IF
return_if_stmts ::= _stmts . return_if_stmt
return_stmts ::= _stmts . return_stmt
returns ::= _stmts . return
slice0 ::= expr . DUP_TOP SLICE+0
slice0 ::= expr . SLICE+0
slice1 ::= expr . expr DUP_TOPX_2 SLICE+1
slice1 ::= expr . expr SLICE+1
slice2 ::= expr . expr DUP_TOPX_2 SLICE+2
slice2 ::= expr . expr SLICE+2
slice3 ::= expr . expr expr DUP_TOPX_3 SLICE+3
slice3 ::= expr . expr expr SLICE+3
stmt ::= continue .
stmt ::= ifelsestmt .
stmt ::= print_items_nl_stmt .
stmt ::= print_items_stmt .
store ::= STORE_FAST .
subscript ::= expr . expr BINARY_SUBSCR
subscript2 ::= expr . expr DUP_TOPX_2 BINARY_SUBSCR
suite_stmts ::= _stmts .
suite_stmts ::= continues .
testexpr ::= testfalse .
testfalse ::= expr . jmp_false
testfalse ::= expr jmp_false .
testtrue ::= expr . jmp_true
unary_convert ::= expr . UNARY_CONVERT
unary_not ::= expr . UNARY_NOT
unary_op ::= expr . unary_operator
while1elsestmt ::= SETUP_LOOP . l_stmts JUMP_BACK POP_BLOCK else_suitel COME_FROM
while1elsestmt ::= SETUP_LOOP . l_stmts JUMP_BACK else_suitel COME_FROM
while1stmt ::= SETUP_LOOP . l_stmts_opt CONTINUE COME_FROM
while1stmt ::= SETUP_LOOP . l_stmts_opt JUMP_BACK COME_FROM
while1stmt ::= SETUP_LOOP . l_stmts_opt JUMP_BACK POP_BLOCK COME_FROM
while1stmt ::= SETUP_LOOP . returns COME_FROM
while1stmt ::= SETUP_LOOP . returns pb_come_from
while1stmt ::= SETUP_LOOP \e_l_stmts_opt . CONTINUE COME_FROM
while1stmt ::= SETUP_LOOP \e_l_stmts_opt . JUMP_BACK COME_FROM
while1stmt ::= SETUP_LOOP \e_l_stmts_opt . JUMP_BACK POP_BLOCK COME_FROM
whileelsestmt ::= SETUP_LOOP . testexpr \e_l_stmts_opt JUMP_BACK POP_BLOCK else_suitel COME_FROM
whileelsestmt ::= SETUP_LOOP . testexpr l_stmts_opt JUMP_BACK POP_BLOCK else_suitel COME_FROM
whilestmt ::= SETUP_LOOP . testexpr \e_l_stmts_opt JUMP_BACK JUMP_BACK POP_BLOCK \e__come_froms
whilestmt ::= SETUP_LOOP . testexpr \e_l_stmts_opt JUMP_BACK JUMP_BACK POP_BLOCK _come_froms
whilestmt ::= SETUP_LOOP . testexpr \e_l_stmts_opt JUMP_BACK POP_BLOCK \e__come_froms
whilestmt ::= SETUP_LOOP . testexpr \e_l_stmts_opt JUMP_BACK POP_BLOCK _come_froms
whilestmt ::= SETUP_LOOP . testexpr l_stmts_opt JUMP_BACK JUMP_BACK POP_BLOCK \e__come_froms
whilestmt ::= SETUP_LOOP . testexpr l_stmts_opt JUMP_BACK JUMP_BACK POP_BLOCK _come_froms
whilestmt ::= SETUP_LOOP . testexpr l_stmts_opt JUMP_BACK POP_BLOCK \e__come_froms
whilestmt ::= SETUP_LOOP . testexpr l_stmts_opt JUMP_BACK POP_BLOCK _come_froms
whilestmt ::= SETUP_LOOP . testexpr returns \e__come_froms POP_BLOCK COME_FROM
whilestmt ::= SETUP_LOOP . testexpr returns _come_froms POP_BLOCK COME_FROM
with ::= expr . SETUP_WITH POP_TOP \e_suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
with ::= expr . SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
withasstmt ::= expr . SETUP_WITH store \e_suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
withasstmt ::= expr . SETUP_WITH store suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH WITH_CLEANUP END_FINALLY
yield ::= expr . YIELD_VALUE
Instruction context:
L. 11 49 LOAD_GLOBAL 5 'Hello'
52 PRINT_ITEM
53 PRINT_NEWLINE_CONT
-> 54 JUMP_ABSOLUTE 60 'to 60'
57 JUMP_BACK 10 'to 10'
60 JUMP_BACK 10 'to 10'
63 POP_BLOCK
class Test:
elements = []
def test--- This code section failed: ---
L. 4 0 SETUP_LOOP 61 'to 64'
3 LOAD_GLOBAL 0 'Test'
6 LOAD_ATTR 1 'elements'
9 GET_ITER
10 FOR_ITER 50 'to 63'
13 STORE_FAST 1 'element'
L. 5 16 LOAD_FAST 1 'element'
19 LOAD_ATTR 2 'a'
22 POP_JUMP_IF_FALSE 10 'to 10'
L. 6 25 LOAD_FAST 1 'element'
28 LOAD_ATTR 3 'b'
31_0 COME_FROM 22 '22'
31 POP_JUMP_IF_FALSE 10 'to 10'
L. 7 34 JUMP_FORWARD 3 'to 40'
L. 9 37 CONTINUE 10 'to 10'
40_0 COME_FROM 34 '34'
L. 10 40 LOAD_FAST 1 'element'
43 LOAD_ATTR 4 'c'
46 POP_JUMP_IF_FALSE 60 'to 60'
L. 11 49 LOAD_GLOBAL 5 'Hello'
52 PRINT_ITEM
53 PRINT_NEWLINE_CONT
54 JUMP_ABSOLUTE 60 'to 60'
57 JUMP_BACK 10 'to 10'
60 JUMP_BACK 10 'to 10'
63 POP_BLOCK
64_0 COME_FROM 0 '0'
Parse error at or near `JUMP_ABSOLUTE' instruction at offset 54
# file test.3.pyc
# Deparsing stopped due to parse error
Additional information
If pass is replaced with print Foo, the error changes to the line of LOAD_FAST associated to element of element.c.
It seems jumps pointers cache doesn't like this level of embedding inside condition blocks: if I move the instructions to a higher level, the problem vanishes.
For instance, this code is fine:
Code
class Test():
elements = []
def test(self):
for element in Test.elements:
if element.a:
pass
else:
continue
if element.c:
print Hello