--- tags: decompiler --- # Pyc Analysis [16 July] - Different Python versions perform better in different aspects - Async functions trouble some more than other Stats Summary: | **Python Version:** | Py3.8 | Py3.7 | Py3.6 | Py2.7 | | -------- | -------- | -------- | -------- | -------- | | **Success rate:** | 7/28 | 13/28 | 18/28 | 22/24 | > Not counting async functions towards python 2.7 ## Version variations - Python 3.6 performs better than python 3.7 and 3.8 - However, cannot substitute python 3.6 with 3.7 and 3.8 (see [MWE 1/3](https://hackmd.io/@aliahad97/rkPmyJCpO#Error-13)). - Cases where Python 2.7 and 3.6 fail while 3.7 and 3.8 pass (see [MWE 1/8](https://hackmd.io/@aliahad97/rkPmyJCpO#Error-18)) - Migration is not always the solution since in some cases all python 3 fail and each of them have different bytecode - Async introduces a whole new range of issues ### Python variation: #### Python 3.6 fail: Bytecode variation for [MWE 1/3](https://hackmd.io/@aliahad97/rkPmyJCpO#Error-13): For code: ```python= def _on_item_clicked(): for x in items(): if x: if is_modified: if not is_selected: deselect() else: deselect() else: select() ``` Bytecode: ![](https://i.imgur.com/KOYGS7m.jpg) <- Python 3.8 on left | Python 3.6 on right -> **Key takeaways:** - Fix the following: - Change Setup loop - Fix offsets - Change header to python 3.8 bytecode - Should decompyle #### Python 3.6 and 2.7 fail: Bytecode variation for [MWE 1/8](https://hackmd.io/@aliahad97/rkPmyJCpO#Error-18): For code: ```python= def __setitem__(self, key, value, unrepr=False): if not self.main.stringify: if a: pass elif b: x= 1 else: x= 2 ``` Bytecode for 3.6 and 2.7: ![](https://i.imgur.com/8A6Ypvr.jpg) Both fail. <- Python 3.6 on left | Python 2.7 on right -> Bytecode for 3.6 and 3.8: ![](https://i.imgur.com/QdBH75z.jpg) <- Python 3.6 on left | Python 3.8 on right -> **Key takeaways:** - Fix the following: - Migrate python 2.7 to 3 - Change header to python 3.8 bytecode - Should decompyle #### All python3 fail: Bytecode variation for [MWE 1/15](https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-115): For code: ```python= def remove_sections(): return x for start in sections: pass ``` Bytecode for 3.6 and 2.7: ![](https://i.imgur.com/WVl8kkZ.png) <- Python 3.6 on left | Python 2.7 on right -> Bytecode for 3.6 and 3.8: ![](https://i.imgur.com/wPscUKA.png) <- Python 3.6 on left | Python 3.8 on right -> **Key takeaways:** - Migrating from different Python 3 versions to 2.7 is complex - Cases as such require approach different from migration - Fix the following: - Remove bytecode below return statement - Should decompyle #### Async functions and python versions MWEs related to async: - [MWE 1/11](https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-111) - [MWE 1/12](https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-112) - [MWE 1/13](https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-113) - [MWE 1/14](https://hackmd.io/@aliahad97/BJNrSJ0pd#Error-114) | **Python Version:** | Py3.8 | Py3.7 | Py3.6 | Py2.7 | | -------- | -------- | -------- | -------- | -------- | | **Success rate:** | 1/4 | 3/4 | 1/4 | N/A | For code in python 3.6: ```python= async def flatten(self): l = [] async for result in self: l.append(result) return l ``` > Note: This fails to decompyle Bytecode with and without async: ![](https://i.imgur.com/kvKRsE1.jpg) Bytecode for 3.6 and 3.7: ![](https://i.imgur.com/SQ46fpQ.jpg) <- Python 3.6 on left | Python 3.7 on right -> Here Python 3.7 Passes in decompilation. Overall Python 3.7 performs best for async functions. **Key takeaways:** - Async functions add a range of code that would be absent otherwise - Python 3.7 performs best - There is no case where other python versions pass for async functions when python 3.7 fails - Fix the following: - Migrate to python 3.7 by changing highlighted bytecode - Change header to python 3.7 - Should decompyle