---
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:

<- 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:

Both fail.
<- Python 3.6 on left | Python 2.7 on right ->
Bytecode for 3.6 and 3.8:

<- 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:

<- Python 3.6 on left | Python 2.7 on right ->
Bytecode for 3.6 and 3.8:

<- 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:

Bytecode for 3.6 and 3.7:

<- 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