---
tags: decompiler
title: Other decompilers
---
# Unpyc37
Total: 5356
Exception raised: 33 (Explicit errors)
Attribution error: 37
Total exceptions: 80
debugging: `Traceback (most recent call last):`
How to find implicit errors?
- Inconsistencies in bytecode functions: 4086
- prune out those that are still equivalent?
- Find jump instructions diff
Example:
:::spoiler
Example 1 (15660):
```
def _download_impl(self, url, pathfmt):
while True:
if tries:
if response:
response.close()
response = None
self.log.warning("%s (%s/%s)", msg, tries, self.retries+1)
if tries > self.retries:
return False
time.sleep(tries)
tries += 1
file_header = None
# collect HTTP headers
headers = {"Accept": "*/*"}
# file-specific headers
extra = kwdict.get("_http_headers")
if extra:
headers.update(extra)
# general headers
if self.headers:
headers.update(self.headers)
# partial content
file_size = pathfmt.part_size()
if file_size:
headers["Range"] = "bytes={}-".format(file_size)
# connect to (remote) source
try:
response = self.session.request(
kwdict.get("_http_method", "GET"), url,
stream=True,
headers=headers,
data=kwdict.get("_http_data"),
timeout=self.timeout,
proxies=self.proxies,
verify=self.verify,
)
except (ConnectionError, Timeout) as exc:
msg = str(exc)
continue
except Exception as exc:
self.log.warning(exc)
return False
# check response
code = response.status_code
if code == 200: # OK
offset = 0
size = response.headers.get("Content-Length")
elif code == 206: # Partial Content
offset = file_size
size = response.headers["Content-Range"].rpartition("/")[2]
elif code == 416 and file_size: # Requested Range Not Satisfiable
break
else:
msg = "'{} {}' for '{}'".format(code, response.reason, url)
tmp = code == 429 or 500 <= code < 600 ## LOOK HEREEE!!!!! XXX
if tmp: # Server Error
continue
self.log.warning(msg)
return False
# check for invalid responses
validate = kwdict.get("_http_validate")
if validate:
result = validate(response)
if isinstance(result, str):
url = result
tries -= 1
continue
if not result:
self.log.warning("Invalid response")
return False
# set missing filename extension from MIME type
if not pathfmt.extension:
pathfmt.set_extension(self._find_extension(response))
if pathfmt.exists():
pathfmt.temppath = ""
return True
# check file size
size = text.parse_int(size, None)
if size is not None:
if self.minsize and size < self.minsize:
self.log.warning(
"File size smaller than allowed minimum (%s < %s)",
size, self.minsize)
return False
if self.maxsize and size > self.maxsize:
self.log.warning(
"File size larger than allowed maximum (%s > %s)",
size, self.maxsize)
return False
content = response.iter_content(self.chunk_size)
# check filename extension against file header
if adjust_extension and not offset and \
pathfmt.extension in FILE_SIGNATURES:
try:
file_header = next(
content if response.raw.chunked
else response.iter_content(16), b"")
except (RequestException, SSLError, OpenSSLError) as exc:
msg = str(exc)
print()
continue
if self._adjust_extension(pathfmt, file_header) and \
pathfmt.exists():
pathfmt.temppath = ""
return True
# set open mode
if not offset:
mode = "w+b"
if file_size:
self.log.debug("Unable to resume partial download")
else:
mode = "r+b"
self.log.debug("Resuming download at byte %d", offset)
# download content
self.downloading = True
with pathfmt.open(mode) as fp:
if file_header:
fp.write(file_header)
offset += len(file_header)
elif offset:
if adjust_extension and \
pathfmt.extension in FILE_SIGNATURES:
self._adjust_extension(pathfmt, fp.read(16))
fp.seek(offset)
self.out.start(pathfmt.path)
try:
self.receive(fp, content, size, offset)
except (RequestException, SSLError, OpenSSLError) as exc:
msg = str(exc)
print()
continue
# check file size
if size and fp.tell() < size:
msg = "file size mismatch ({} < {})".format(
fp.tell(), size)
print()
continue
break
self.downloading = False
if self.mtime:
kwdict.setdefault("_mtime", response.headers.get("Last-Modified"))
else:
kwdict["_mtime"] = None
return True
```
:::
# Uncompyle2
Total: 22222
Parse errors (explicit): 36
Implicit errors?
# Pycdc
## Segmentation fault
Segmentation fault
Errors:
### Py27
pattern1:
```
if x:
return
#z=z
return {a: b}
```
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern3:
```
assert X
#z=z
for i in x:
pass
```
pattern4:
```
if not _winreg:
return
#z=z
def enum_types(mimedb):
pass
```
pattern5:
```
if not _winreg:
return
#z=z
for i in x:
pass
```
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
Pattern7:
```
if not hasattr(os, 'utime'):
return
#z=z
try:
os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
except EnvironmentError as e:
raise ExtractError('could not change modification time')
```
Pattern 8:
```
try:
if a:
return b
#z=z
except OSError as msg:
raise URLError(msg)
```
Pattern 9:
```
if a:
if b:
if c:
k = k + 1
# z=z
temp = temp + 1
```
### Py34
Infinitely runs:
Pattern 3:
```
assert action_tuples
z=z
for action, args, option_string in action_tuples:
take_action(action, args, option_string)
```
Pattern 10:
```
while True: # change to temp
if action is None:
extras.append(arg_strings[start_index])
# return start_index + 1
if a:
arg_count = match_argument(action, 'A')
else:
break
```
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
### py35
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
Pattern 11:
```
assert x
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern4:
```
if not _winreg:
return
#z=z
def enum_types(mimedb):
pass
```
Pattern 8:
```
try:
if a:
return b
#z=z
except OSError as msg:
raise URLError(msg)
```
pattern3:
```
assert X
#z=z
for i in x:
pass
```
Pattern 12:
```
if a:
b = b +1
else:
return
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
Pattern 13:
```
try:
if fut is not None:
# assign following boolean to a variable
assert self._read_fut is fut or not (self._read_fut is None and
self._closing)
except ConnectionAbortedError as exc:
pass
```
### py36
Pattern 8:
```
try:
if a:
return b
#z=z
except OSError as msg:
raise URLError(msg)
```
pattern3:
```
assert X
#z=z
for i in x:
pass
```
Pattern 10:
```
while True: # change to temp
if action is None:
extras.append(arg_strings[start_index])
# return start_index + 1
if a:
arg_count = match_argument(action, 'A')
else:
break
```
Pattern 11:
```
assert x
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
Pattern 13:
```
try:
if fut is not None:
# assign following boolean to a variable
assert self._read_fut is fut or not (self._read_fut is None and
self._closing)
except ConnectionAbortedError as exc:
pass
```
pattern4:
```
if not _winreg:
return
#z=z
def enum_types(mimedb):
pass
```
Pattern 8:
```
try:
if a:
return b
#z=z
except OSError as msg:
raise URLError(msg)
```
### py37
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
pattern3:
```
assert X
#z=z
for i in x:
pass
```
Pattern 10:
```
while True: # change to temp
if action is None:
extras.append(arg_strings[start_index])
# return start_index + 1
if a:
arg_count = match_argument(action, 'A')
else:
break
```
Pattern 11:
```
assert x
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern4:
```
if not _winreg:
return
#z=z
def enum_types(mimedb):
pass
```
Pattern 8:
```
try:
if a:
return b
#z=z
except OSError as msg:
raise URLError(msg)
```
Pattern 13:
```
try:
if fut is not None:
# assign following boolean to a variable
assert self._read_fut is fut or not (self._read_fut is None and
self._closing)
except ConnectionAbortedError as exc:
pass
```
pattern5:
```
if not _winreg:
return
#z=z
for i in x:
pass
```
Pattern 14:
```
# tmp =(2, 7) < version_info[:2] < (3, 2)
if (2, 7) < version_info[:2] < (3, 2): #tmp:
import collections
def callable(x):
return isinstance(x, collections.Callable)
else:
callable = callable
```
### py38
Pattern 11:
Pattern6:
```
assert unicodedata.unidata_version == '3.2.0'
#z=z
def in_table_a1(code):
pass
```
```
assert x
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
pattern 15:
```
for i in x:
if a:
raise URLError(msg)
#z=z
```
Pattern 14:
```
# tmp =(2, 7) < version_info[:2] < (3, 2)
if (2, 7) < version_info[:2] < (3, 2): #tmp:
import collections
def callable(x):
return isinstance(x, collections.Callable)
else:
callable = callable
```
pattern2:
```
if cmd == '':
return self.default(line)
#z=z
try:
func = getattr(self, 'do_' + cmd)
except AttributeError:
return self.default(line)
```
Pattern 10:
```
while True: # change to temp
if action is None:
extras.append(arg_strings[start_index])
# return start_index + 1
if a:
arg_count = match_argument(action, 'A')
else:
break
```
Pattern 16:
```
for line in source.split("\n"):
line = line.strip()
if line and line[0] != '#':
break # comment this
```
pattern4:
```
if not _winreg:
return
#z=z
def enum_types(mimedb):
pass
```
Pattern 17:
```
for kind in ('episode', 'clip'):
common_data = (cache.get(current_key) or list(cache.values())[0])[kind]
break # remove
```