Skip to content
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

Have a compiled file that fails to decompile #405

Open
bdezonia opened this issue Aug 22, 2022 · 4 comments
Open

Have a compiled file that fails to decompile #405

bdezonia opened this issue Aug 22, 2022 · 4 comments

Comments

@bdezonia
Copy link

bdezonia commented Aug 22, 2022

Description

I am a developer who has inherited some code. We have a .pyc file (and not the original .py file) that we need to decompile to figure out what it does. I am attaching the .pyc file and some of the decompilation results from an attempted decomp. It almost succeeds but has a section of byte code in the middle it is not happy with. It looks like a COME_FROM address 92 does not have a JUMP to of any kind at address 92.

How to Reproduce

uncompyle6 bmrb.pyc > bmrb.py

Output Given

    def __setitem__--- This code section failed: ---

 L.1481         0  LOAD_GLOBAL           0  'isinstance'
                3  LOAD_FAST             2  'item'
                6  LOAD_GLOBAL           1  'Saveframe'
                9  CALL_FUNCTION_2       2  None
               12  JUMP_IF_FALSE       170  'to 185'
               15  POP_TOP          

 L.1483        16  SETUP_EXCEPT         17  'to 36'

 L.1484        19  LOAD_FAST             2  'item'
               22  LOAD_FAST             0  'self'
               25  LOAD_ATTR             2  'frame_list'
               28  LOAD_FAST             1  'key'
               31  STORE_SUBSCR     
               32  POP_BLOCK        
               33  JUMP_ABSOLUTE       198  'to 198'
             36_0  COME_FROM            16  '16'

 L.1485        36  DUP_TOP          
               37  LOAD_GLOBAL           3  'TypeError'
               40  COMPARE_OP           10  exception-match
               43  JUMP_IF_FALSE       134  'to 180'
               46  POP_TOP          
               47  POP_TOP          
               48  POP_TOP          
               49  POP_TOP          

 L.1487        50  LOAD_FAST             1  'key'
               53  LOAD_FAST             0  'self'
               56  LOAD_ATTR             4  'frame_dict'
               59  CALL_FUNCTION_0       0  None
               62  COMPARE_OP            6  in
               65  JUMP_IF_FALSE        92  'to 160'
               68  POP_TOP          

 L.1488        69  LOAD_GLOBAL           5  'dict'
               72  LOAD_GENEXPR             '<code_object <genexpr>>'
               75  MAKE_FUNCTION_0       0  None
               78  LOAD_FAST             0  'self'
               81  LOAD_ATTR             2  'frame_list'
               84  GET_ITER         
               85  CALL_FUNCTION_1       1  None
               88  CALL_FUNCTION_1       1  None
               91  POP_TOP          

 L.1489        92  SETUP_LOOP           82  'to 177'
               95  LOAD_GLOBAL           6  'enumerate'
               98  LOAD_FAST             0  'self'
              101  LOAD_ATTR             2  'frame_list'
              104  CALL_FUNCTION_1       1  None
              107  GET_ITER         
              108  FOR_ITER             45  'to 156'
              111  UNPACK_SEQUENCE_2     2 
              114  STORE_FAST            3  'pos'
              117  STORE_FAST            4  'frame'

 L.1490       120  LOAD_FAST             4  'frame'
              123  LOAD_ATTR             7  'name'
              126  LOAD_FAST             1  'key'
              129  COMPARE_OP            2  ==
              132  JUMP_IF_FALSE        17  'to 152'
              135  POP_TOP          

 L.1491       136  LOAD_FAST             2  'item'
              139  LOAD_FAST             0  'self'
              142  LOAD_ATTR             2  'frame_list'
              145  LOAD_FAST             3  'pos'
              148  STORE_SUBSCR     
              149  JUMP_BACK           108  'to 108'
            152_0  COME_FROM           132  '132'
              152  POP_TOP          
              153  JUMP_BACK           108  'to 108'
              156  POP_BLOCK        
              157  JUMP_ABSOLUTE       182  'to 182'
            160_0  COME_FROM            65  '65'
              160  POP_TOP          

 L.1493       161  LOAD_GLOBAL           8  'KeyError'
              164  LOAD_CONST               "Saveframe with name '%s' does not exist and therefore cannot be written to. Use the add_saveframe method to add new saveframes."

 L.1496       167  LOAD_FAST             1  'key'
              170  BINARY_MODULO    
              171  CALL_FUNCTION_1       1  None
              174  RAISE_VARARGS_1       1  None
            177_0  COME_FROM            92  '92'
              177  JUMP_ABSOLUTE       198  'to 198'
              180  POP_TOP          
              181  END_FINALLY      
              182  JUMP_FORWARD         13  'to 198'
            185_0  COME_FROM            12  '12'
              185  POP_TOP          

 L.1498       186  LOAD_GLOBAL           9  'ValueError'
              189  LOAD_CONST               'You can only assign an entry to a saveframe splice.'
              192  CALL_FUNCTION_1       1  None
              195  RAISE_VARARGS_1       1  None
            198_0  COME_FROM           182  '182'

Parse error at or near `COME_FROM' instruction at offset 177_0

Environment

Python version 3.8.10
bmrb.pyc.zip

@rocky
Copy link
Owner

rocky commented Aug 22, 2022

It looks like a COME_FROM address 92 does not have a JUMP to of any kind at address 92.

What that is saying is that the SETUP_LOOP at offset 92 jumps here when the loop terminates.

@rocky
Copy link
Owner

rocky commented Aug 23, 2022

For what it is worth, I can write Python 2.6 code that seems functionally equivalent, but doesn't compile to the same bytecode in Python 2.6.9.

It is possible that this was compiled by an earlier version of Python 2.6 which may explain the bytecode discrepancy.

Therefore, fixing this will have to wait for some situation where we have the source code to compare against that has the same kind of characterstic.

@bdezonia
Copy link
Author

Ok, thanks for the update. It being compiled using python before 2.6.9 would not surprise me. This code is on an old server.

If you have a guess as to what the routine originally looked like please pass along a snippet. With a little study of the byte code listing above and a python snippet guess It might help me reconstruct what it was trying to do.

@rocky
Copy link
Owner

rocky commented Aug 24, 2022

If you make a donation to the project, I will post a guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants