Skip to content

Conversation

@rocky
Copy link
Owner

@rocky rocky commented Nov 25, 2025

Bug identified by @wangym5106 in #521 where the optype of a list is using a constant list's constant number index instead of its value.

@wangym5106
Copy link
Contributor

wangym5106 commented Nov 27, 2025

Just tried this branch, seems fixed optype == None, (so it can be merged) , but the original issue is not fully fixed.
For py3.12 uncompyle6 decompiles py2.7 pyc, the quotes is missing

test = ['a', 'b', 'c', 'd', 'e', 'f']
test2 = [101, 102, 103, 1.4, 1.5]

# Python bytecode version base 2.7 (62211)
#   Decompiled from: Python 3.12.10 (tags/v3.12.10:0cc8128, Apr  8 2025, 12:21:36) [MSC v.1943 64 bit (AMD64)]
# Embedded file name: /cwd/test.py
# Compiled at: 2025-11-27 10:09:06
test = [
 a, b, c, d, e, f]
test2 = [101, 102, 103, 1.4, 1.5]
return

# okay decompiling .\test.pyc

For For py3.12 uncompyle6 decompiles py3.8 pyc, it's correct. Didn't test py2.7 uncompyle6 decompiles py2.7 pyc.

If I change L279 value = elem.pattr to value = repr(elem.pattr) , the python2 pyc is correct but python3 pyc is wrong.

# Python bytecode version base 3.8.0 (3413)
#   Decompiled from: Python 3.12.10 (tags/v3.12.10:0cc8128, Apr  8 2025, 12:21:36) [MSC v.1943 64 bit (AMD64)]
# Embedded file name: .\test3.py
# Compiled at: 2025-11-27 10:10:25
# Size of source mod 2**32: 72 bytes
test = [
 '"a"', '"b"', '"c"', '"d"', '"e"', '"f"']
test2 = [101, 102, 103, 1.4, 1.5]

# okay decompiling .\__pycache__\test3.cpython-38.pyc

The difference between python 2 and python 3 still exist.
When decompile python2 pyc:
attr = 0 pattr = a
When decompile python3 pyc:
attr = a pattr = "a"
Maybe we should change these args, on par with std dis, for example:
arg = 0 argval = a argrepr = "a"
I also found a FIXME mentioned it. Is this requires changing xdis? It seems need a lot of change to the scanner?

@rocky
Copy link
Owner Author

rocky commented Nov 27, 2025

If xdis is not following dis, that should be fixed. And the FIXME, following xdis's conventions, should be fixed as well.

Sadly, it took a while to come up with a plan or strategy that might accommodate all the variations in Python versions and implementations. So there's a bit of work in uncompyle6 (and/or xdis) that needs to go on.

@wangym5106
Copy link
Contributor

If the direction is correct, we can merge this first. (#521 and #522 is optional as a temporary workaround).
I'll look at the scanner to see what I can do.

@rocky
Copy link
Owner Author

rocky commented Nov 28, 2025

OK. I look forward to what you come up with on the scanner.

Things should be consistent where they haven't been before. We need to distinguish

  • the operand value as it appears after the opcode
  • a resolved value which is the Python object when it makes sense. For items in the code object's const and names tables, this is often just a particular table, indexed by the operand table. For jump operands, it is the offset address that is getting jumped to.
  • a print representation of the resolved value. For jumps it can be "to offset xxx"; for flags it is the string representation of the flags; for calls it is the interpretation of the call flags which is sometimes how many arguments the call has, whether it has annotations or takes keyword arguments.

@rocky rocky merged commit b621b01 into master Nov 28, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants