rocky / python-uncompyle6

A cross-version Python bytecode decompiler
GNU General Public License v3.0
3.74k stars 408 forks source link

"if else" condition generates "uncompyle6.semantics.pysource.SourceWalkerError: Deparsing stopped due to parse error" #321

Open josephernest opened 4 years ago

josephernest commented 4 years ago

If you compile this test.py into a .pyc (with import py_compile; py_compile.compile("test.py")):

def f():
    L = []
    if len(L) > 1:
        if 1:
            pass
        else:
            pass
    else:
        pass

then decompiling it with uncompyle6 with

with open('test_decompiled.py', 'w') as f:
    uncompyle6.decompile_file(r'__pycache__\test.cpython-37.pyc', f)

generates this error:

uncompyle6.semantics.pysource.SourceWalkerError: Deparsing stopped due to parse error

Here is the full error:

# uncompyle6 version 3.7.1
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: test-class.py
# Compiled at: 2020-06-16 19:00:25
# Size of source mod 2**32: 131 bytes

def f--- This code section failed: ---

 L.   2         0  BUILD_LIST_0          0 
                2  STORE_FAST               'L'

 L.   3         4  LOAD_GLOBAL              len
                6  LOAD_FAST                'L'
                8  CALL_FUNCTION_1       1  '1 positional argument'
               10  LOAD_CONST               1
               12  COMPARE_OP               >
               14  POP_JUMP_IF_FALSE    18  'to 18'

 L.   5        16  JUMP_FORWARD         18  'to 18'
             18_0  COME_FROM            16  '16'
             18_1  COME_FROM            14  '14'

Parse error at or near `COME_FROM' instruction at offset 18_0
josephernest commented 4 years ago

@rocky I found an even more minimal example:

L = []
if len(L) > 1:
    pass
else:
    pass

Error log:

L.   1         0  BUILD_LIST_0          0 
                2  STORE_NAME               L

 L.   2         4  LOAD_NAME                len
                6  LOAD_NAME                L
                8  CALL_FUNCTION_1       1  '1 positional argument'
               10  LOAD_CONST               1
               12  COMPARE_OP               >
               14  POP_JUMP_IF_FALSE    18  'to 18'

 L.   3        16  JUMP_FORWARD         18  'to 18'
             18_0  COME_FROM            16  '16'
             18_1  COME_FROM            14  '14'

Parse error at or near `COME_FROM' instruction at offset 18_0
rocky commented 4 years ago

Both examples have been addressed in the decompyle3 project. However the massive grammar changes needs to be backported here.

josephernest commented 4 years ago

have been addressed in the decompyle6 project

@rocky what is the decompyle6 project? Is it different to uncompyle6?

rocky commented 4 years ago

https://github.com/rocky/python-uncompyle6#see-also

josephernest commented 4 years ago

decompyle6 project

Do you mean decompile3?

QGB commented 6 months ago

Parse error at or near `POP_EXCEPT' instruction at offset 276