Skip to content

Python 3.13 decompilation fails (MAKE_FUNCTION, CALL_KW, TO_BOOL) + 3.14 magic not recognized #606

Description

@hexmode

Python 3.13 decompilation fails (MAKE_FUNCTION, CALL_KW, TO_BOOL) + Python 3.14 magic not recognized

Environment:

  • pycdc master branch at b428976 (April 2026)
  • Target: Python 3.13.0 pyc files (magic 0x0df3 = 3571)
  • Target: Python 3.14.2 pyc files (magic 0x0e2b = 3627)
  • OS: Linux, gcc 14.2.0

Issue 1: Python 3.14 magic number missing

pycdas and pycdc both report Bad MAGIC! for Python 3.14 pyc files. Magic 0x0e2b (3627) is not in the magic detection table in data.cpp. The greenozon/pycdc fork has a py314 branch but it also lacks this magic entry (it has the same issue).

Issue 2: Python 3.13 MAKE_FUNCTION opcode mismatch

The 3.13 bytecode mapping (bytes/python_3_13.cpp) maps opcode 26 to MAKE_FUNCTION. However, CPython 3.13 final uses opcode 122 for MAKE_FUNCTION. The opcode numbering seems to be from a 3.13 pre-release where numbers differed.

Result: pycdc prints Unsupported opcode: MAKE_FUNCTION (122) and produces only imports/signatures with function bodies stubbed to pass.

Issue 3: CALL_KW (247) and TO_BOOL (123) unsupported on 3.13

Even when MAKE_FUNCTION is handled (e.g., on PR #579 branch), pycdc hits:

  • Unsupported opcode: CALL_KW (247) — used for click.option(...) and re.match(...) calls
  • Unsupported opcode: TO_BOOL (123) — used extensively for truthiness checks (if, and, or)

These are new Python 3.13 opcodes (PEP 709 and related changes) that need AST builder support.

Reproduction:

You can reproduce with the attached 3.13 pyc file. Build master, then:

$ pycdc cli.cpython-313.pyc
Unsupported opcode: MAKE_FUNCTION (122)
...
# WARNING: Decompyle incomplete

Where pycdas works fully:

$ pycdas cli.cpython-313.pyc
# Full disassembly output with correct opcodes

pycdas output confirming the real opcode numbers:

70      MAKE_FUNCTION                   ← opcode at offset 70
72      SET_FUNCTION_ATTRIBUTE          4 (MAKE_FUNCTION_ANNOTATIONS)
...
38      CALL                            2
46      TO_BOOL                         ← opcode at offset 46
...
182     CALL_KW                         12

The raw bytecode confirms these use CPython 3.13's actual opcode numbers, not pycdc's mapped 3.13 numbers.

Suggested fixes:

  1. Add magic 0x0e2b to data.cpp for Python 3.14, with corresponding bytes/python_3_14.cpp
  2. Update bytes/python_3_13.cpp to use CPython 3.13 final's opcode numbering
  3. Add handlers in ASTree.cpp for CALL_KW (converting to regular function call with keyword args) and TO_BOOL (converting to truthiness check, similar to existing boolean handling)
  4. Verify with a real 3.13 final pyc file rather than pre-release numbering

I can provide the test pyc files if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions