-
-
Notifications
You must be signed in to change notification settings - Fork 448
Description
Description
Attempting to decompile a tkinter script which was extracted from a PyInstaller executable. I got this error:
Traceback (most recent call last):
File "~/.local/bin/uncompyle6", line 10, in <module>
sys.exit(main_bin())
File "~/.local/lib/python3.6/site-packages/uncompyle6/bin/uncompile.py", line 194, in main_bin
**options)
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 327, in main
do_fragments,
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 225, in decompile_file
do_fragments=do_fragments,
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 144, in decompile
co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy
File "~/.local/lib/python3.6/site-packages/uncompyle6/semantics/pysource.py", line 2531, in code_deparse
co, code_objects=code_objects, show_asm=debug_opts["asm"]
File "~/.local/lib/python3.6/site-packages/uncompyle6/scanners/scanner38.py", line 106, in ingest
jump_back_index = self.offset2tok_index[jump_target] - 1
KeyError: 4416It seemed like an interesting and simple-ish issue so I decided to investigate! With this code below line 101, I found the problem.
| # jump target instruction. |
if token.attr == 4416:
print()
print(vars(token))
print({i: self.offset2tok_index[i] for i in self.offset2tok_index if '4416' in str(i)})This was the output:
{'kind': 'JUMP_ABSOLUTE', 'has_arg': True, 'attr': 4416, 'pattr': 4416, 'offset': 2428, 'linestart': None, 'opc': <module 'xdis.opcodes.opcode_38' from '~/.local/lib/python3.6/site-packages/xdis/opcodes/opcode_38.py'>, 'op': 113}
{'4416_0': 2222, '4416_1': 2223, '4416_4418': 2224}I noticed that there was no 4416 key - all of the keys had _... values. After a bit more digging I saw that it was being added by these lines:
python-uncompyle6/uncompyle6/scanners/scanner37base.py
Lines 329 to 340 in 451f0b5
| j = tokens_append( | |
| j, | |
| Token( | |
| come_from_name, | |
| jump_offset, | |
| repr(jump_offset), | |
| offset="%s_%s" % (inst.offset, jump_idx), | |
| has_arg=True, | |
| opc=self.opc, | |
| has_extended_arg=False, | |
| ), | |
| ) |
I don't understand why this JUMP doesn't have the "base" 4416 key, but I found a simple solution. I printed some other JUMP values and noticed that in every case - regardless of 1 or 3+ jumps with the same offset, the jump_back_index is self.offset2tok_index[last_index] - 1 - so in this case, the last 4416 jump is '4416_4418' and thus jump_back_index = self.offset2tok_index['4416_4418'] - 1. I don't understand why, however. So, in short, I changed the code to get the jump_back_index in this way, and it fixed the problem:
From:
| jump_back_index = self.offset2tok_index[jump_target] - 1 |
To:
offset_instances = [inst for inst in self.offset2tok_index if str(jump_target) in str(inst)]
jump_back_index = self.offset2tok_index[offset_instances[-1]] - 1And that fixes this problem.
This issue also applies to https://github.com/rocky/python-decompile3.
How to Reproduce
$ uncompyle6 Main.pyc
Traceback (most recent call last):
File "~/.local/bin/uncompyle6", line 10, in <module>
sys.exit(main_bin())
File "~/.local/lib/python3.6/site-packages/uncompyle6/bin/uncompile.py", line 194, in main_bin
**options)
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 327, in main
do_fragments,
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 225, in decompile_file
do_fragments=do_fragments,
File "~/.local/lib/python3.6/site-packages/uncompyle6/main.py", line 144, in decompile
co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy
File "~/.local/lib/python3.6/site-packages/uncompyle6/semantics/pysource.py", line 2531, in code_deparse
co, code_objects=code_objects, show_asm=debug_opts["asm"]
File "~/.local/lib/python3.6/site-packages/uncompyle6/scanners/scanner38.py", line 106, in ingest
jump_back_index = self.offset2tok_index[jump_target] - 1
KeyError: 4416
$A link to the pyc file: https://gofile.io/?c=MV8jCW