Skip to content

JUMP_ABSOLUTE decompilation error #310

@abmyii

Description

@abmyii

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: 4416

It 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:

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]] - 1

And 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Control FlowProblem has to do with bad control-flow detectionPython 3.8Volunteer wantedVolunteer wanted to fix if a bug or to implement if a new feature.insufficient bug reportThe instructions given when opening a new issue are not followed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions