python-decompile3 icon indicating copy to clipboard operation
python-decompile3 copied to clipboard

Decompilation fails at JUMP_LOOP (with open source example)

Open jnohlgard opened this issue 3 years ago • 2 comments

Description

The parse_dtb function in the pyFDT library fails to decompile with an error at a JUMP_LOOP instruction. Modifying the code within the two while loops in the given example seems to make the bug go away. I have not been able to create a smaller example snippet than this function.

How to Reproduce

Attempt to roundtrip the parse_dtb function in pyFDT. Snippet with the problematic function: https://gist.github.com/jnohlgard/1b0c30769f31a70b5fe67508d4a89924#file-parse_fdt-py Originally from https://github.com/molejar/pyFDT/blob/907089ee05addba01f0f671aa8efea3b723934a1/fdt/init.py#L482-L542

Output Given

Instruction context:
   
 L.  60       528  LOAD_GLOBAL              Exception
                 530  LOAD_STR                 'Unknown Tag: {}'
                 532  LOAD_METHOD              format
                 534  LOAD_FAST                'tag'
                 536  CALL_METHOD_1         1  '1 positional argument'
                 538  CALL_FUNCTION_1       1  '1 positional argument'
                 540  RAISE_VARARGS_1       1  'exception instance'
               542_0  COME_FROM           492  '492'
               542_1  COME_FROM           338  '338'
->               542  JUMP_LOOP           160  'to 160'
                 544  POP_BLOCK        
               546_0  COME_FROM_LOOP      156  '156'
...
Parse error at or near `JUMP_LOOP' instruction at offset 542

Full output: https://gist.github.com/jnohlgard/1b0c30769f31a70b5fe67508d4a89924#file-zzzz-decompyle3-error-log-txt

Expected behavior

Decompiled without errors.

Environment

  • Decompyle3 version: latest master
  • Python version for the version of Python the byte-compiled the file: Python 3.7.13 (default, Mar 18 2022, 11:41:25) [GCC 11.2.1 20220127 (Red Hat 11.2.1-9)]
  • OS and Version: Fedora 35

Workarounds

Not known.

Priority

Additional Context

jnohlgard avatar Apr 21 '22 10:04 jnohlgard

This kind of control flow problem is generally known to be a weakness. I have a long term solution is in the works, but it will probably take a while before there's a public release of this code.

rocky avatar Apr 21 '22 10:04 rocky

If this is still of interest, whittle down the source code to the smallest example that has a problem. Thanks.

rocky avatar Jun 23 '22 11:06 rocky

The below is the shortened code that exhibits the same behavior. If you remove a single assignment statement, the program decompiles.

def parse_dtb(tag, index, current_node):
    while True:
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2
    while True:
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1; index = 2; index = 3
        index = 1
        if index == 1:
            current_node = 5
        elif index == 2:
            if current_node:
                current_node = 7
        elif index == 3:
            if current_node:
                current_node = 8
        else:
            raise Exception

rocky avatar May 28 '23 01:05 rocky