Decompilation fails at JUMP_LOOP (with open source example)
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
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.
If this is still of interest, whittle down the source code to the smallest example that has a problem. Thanks.
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