-
Notifications
You must be signed in to change notification settings - Fork 150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"bad marshal data (unknown type code)" when invoking on pytest .pyc #25
Comments
In debugging https://github.com/rocky/python-uncompyle6 I've come across this a bit. At this point in the code, uncompyle2 is trying to extract a Python code object from the byte-compiled file. It can't. This will most definitely happen if you try to use marshal.load on a version other than the version you are running. But you might say: but I am running the same python version! Maybe and maybe not. In Python 2.7 the magic numbers changed several times in Python 2.7. Here are the changes as best as I know:
There's nothing in the above that I know would change data characteristics needed by a marshal load, so this remains a mystery. However in uncompyle6, I now only will use marshal.loads when the bytecode interpreter number is exactly the same as the running interpreter magic number. (Previously I was just comparing on Python major/minor numbers.) To be not-too much and not-too little one would have to test against the various magic values to see what works and what doesn't. |
Nice explanation, thanks ! |
Perhaps for Python 2 bytecode. You can run it from CPython2 (2.6 or 2.7) or CPython3. For Python3 bytecode, it still needs work. It is easy to come up with lots of tests that cause a failure. One project is organizing the tests better and fixing some of the failures that occur there. But a large number of those also fail, also fail in uncompyle2. (#14 has been fixed though) This and/or the other uncompyle projects all could use help in fixing bugs. |
One other clarification regarding this:
uncompyle2 unconditionally uses marshal.loads() and when this works, it is most-likely correct. This change in behavior was a in commit 09b2adb. The limitation with this is that you can only disassemble Python bytecode that have compatible bytecode formats. So although this project still has opcodes for around for Python 2.3-2.6, it is possible some of these after the commit won't survive a masrhal.loads(). That said, I trust Mysterie to have tested what's is provided here, so I'll assume that they are data compatible. The older code (which is used in the PyPI version of uncompyle2) provides its own marshal load routine written in Python and uncompyle6 uses that as well. As I have recently found, that has problems too when using different versions of Python, especially when going between Python 3 and Python 2. See https://github.com/rocky/python-uncompyle6/blob/master/uncompyle6/marsh.py#L46-L150 and compare with https://github.com/Mysterie/uncompyle2/blob/master/uncompyle2/disas.py#L195-L270 So sorry for the long-winded clarification. What I meant was uncompyle6 uses marshal.loads when the magics are the same, it uses the all-version Python code that is supposed to be equivalent (and probably still has bugs) when the magics are different. |
There is how to reproduce the issue, with the latest version from the repository:
Any idea on the root cause and if it could be fixed ?
The text was updated successfully, but these errors were encountered: