python-uncompyle6
python-uncompyle6 copied to clipboard
Error when decompiling loop inside if-else
I was trying to decompile a pyc that I had, but it had a few errors. I managed to manually decompile it though and narrowed it down to code that looks like this:
def func(val):
if val == 0:
while True:
pass
else:
pass
When I compile this with python3 -m compileall . and then attempt to decompile, I get a 'parse error':
# uncompyle6 version 3.7.2
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.7.7 (default, Jun 28 2020, 13:00:53)
# [GCC 9.3.0]
# Embedded file name: ./code.py
# Compiled at: 2020-06-28 16:30:43
# Size of source mod 2**32: 92 bytes
Instruction context:
L. 4 8 JUMP_BACK 8 'to 8'
-> 10 JUMP_FORWARD 12 'to 12'
12_0 COME_FROM 10 '10'
def func--- This code section failed: ---
L. 2 0 LOAD_FAST 'val'
2 LOAD_CONST 0
4 COMPARE_OP ==
6 POP_JUMP_IF_FALSE 12 'to 12'
L. 4 8 JUMP_BACK 8 'to 8'
10 JUMP_FORWARD 12 'to 12'
12_0 COME_FROM 10 '10'
12_1 COME_FROM 6 '6'
Parse error at or near `JUMP_FORWARD' instruction at offset 10
# file __pycache__/code.cpython-38.pyc
# Deparsing stopped due to parse error
Here is the disassembly of that code:
1 0 LOAD_CONST 0 (<code object func at 0x7ffac2d20b30, file "code.py", line 1>)
2 LOAD_CONST 1 ('func')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (func)
8 LOAD_CONST 2 (None)
10 RETURN_VALUE
Disassembly of <code object func at 0x7ffac2d20b30, file "code.py", line 1>:
2 0 LOAD_FAST 0 (val)
2 LOAD_CONST 1 (0)
4 COMPARE_OP 2 (==)
6 POP_JUMP_IF_FALSE 12
4 >> 8 JUMP_ABSOLUTE 8
10 JUMP_FORWARD 0 (to 12)
6 >> 12 LOAD_CONST 0 (None)
14 RETURN_VALUE
Hopefully this issue can be fixed!
This has been addressed by https://github.com/rocky/python-decompile3/commit/a34740ad9b7f20d6bcf58234e1611240e14ecdfb however the change there needs to be applied here. I'm hoping someone else will put in a PR for that.
Handling on 3.8 will need additional work.
while True:
pass
also this is not work. without inside function or if-else
while True:
pass
is a little bit silly,
2: >> 0 JUMP_ABSOLUTE (to 0)
but if one wanted to handle that, you could probably write a parse custom rule for this.
It's not something though that I feel particularly motivated to work on. However should I need to do so in the future, maybe this will serve as a reminder for what approach to take.