Merge branch 'develop' into features/smt-abs

pull/788/head
JoranHonig 6 years ago committed by GitHub
commit 780e089987
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      mythril/disassembler/disassembly.py
  2. 4
      mythril/ethereum/evmcontract.py
  3. 10
      mythril/interfaces/cli.py
  4. 12
      mythril/mythril.py
  5. 55
      mythril/support/signatures.py
  6. 10
      tests/__init__.py
  7. 4
      tests/mythril_dir/config.ini
  8. BIN
      tests/mythril_dir/signatures.db.example

@ -73,7 +73,7 @@ def get_function_info(
function_names = signature_database.get(function_hash)
if len(function_names) > 1:
# In this case there was an ambiguous result
function_name = "**ambiguous** {}".format(function_names[0])
function_name = "[{}] (ambiguous)".format(", ".join(function_names))
elif len(function_names) == 1:
function_name = function_names[0]
else:

@ -37,6 +37,10 @@ class EVMContract(persistent.Persistent):
return self.disassembly.get_easm()
def get_creation_easm(self):
return self.creation_disassembly.get_easm()
def matches_expression(self, expression):
str_eval = ""

@ -364,10 +364,12 @@ def main():
print(storage)
elif args.disassemble:
easm_text = mythril.contracts[
0
].get_easm() # or mythril.disassemble(mythril.contracts[0])
sys.stdout.write(easm_text)
# or mythril.disassemble(mythril.contracts[0])
if mythril.contracts[0].code:
print("Runtime Disassembly: \n" + mythril.contracts[0].get_easm())
if mythril.contracts[0].creation_code:
print("Disassembly: \n" + mythril.contracts[0].get_creation_easm())
elif args.graph or args.fire_lasers:
if not mythril.contracts:

@ -17,6 +17,7 @@ from solc.exceptions import SolcError
import solc
from configparser import ConfigParser
import platform
from shutil import copyfile
from mythril.ethereum import util
from mythril.ethereum.evmcontract import EVMContract
@ -116,11 +117,18 @@ class Mythril(object):
except KeyError:
mythril_dir = os.path.join(os.path.expanduser("~"), ".mythril")
# Initialize data directory and signature database
if not os.path.exists(mythril_dir):
# Initialize data directory
logging.info("Creating mythril data directory")
os.mkdir(mythril_dir)
db_path = str(Path(mythril_dir) / "signatures.db")
if not os.path.exists(db_path):
# if the default mythril dir doesn't contain a signature DB
# initialize it with the default one from the project root
parent_dir = Path(__file__).parent.parent
copyfile(str(parent_dir / "signatures.db"), db_path)
return mythril_dir
def _init_config(self):

@ -6,12 +6,42 @@ import os
import time
import logging
import sqlite3
import multiprocessing
import functools
from typing import List
from collections import defaultdict
from subprocess import Popen, PIPE
from mythril.exceptions import CompilerError
lock = multiprocessing.Lock()
def synchronized(sync_lock):
""" Synchronization decorator """
def wrapper(f):
@functools.wraps(f)
def inner_wrapper(*args, **kw):
with sync_lock:
return f(*args, **kw)
return inner_wrapper
return wrapper
class Singleton(type):
_instances = {}
@synchronized(lock)
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
try:
# load if available but do not fail
import ethereum_input_decoder
@ -24,7 +54,7 @@ except ImportError:
class SQLiteDB(object):
"""
Simple CM for sqlite3 databases. Commits everything at exit.
Simple context manager for sqlite3 databases. Commits everything at exit.
"""
def __init__(self, path):
@ -45,11 +75,15 @@ class SQLiteDB(object):
return "<SQLiteDB path={}>".format(self.path)
class SignatureDB(object):
class SignatureDB(object, metaclass=Singleton):
def __init__(self, enable_online_lookup: bool = False, path: str = None) -> None:
self.enable_online_lookup = enable_online_lookup
self.online_lookup_miss = set()
self.online_lookup_timeout = 0
# if we're analysing a Solidity file, store its hashes
# here to prevent unnecessary lookups
self.solidity_sigs = defaultdict(list)
if path is None:
self.path = os.environ.get("MYTHRIL_DIR") or os.path.join(
os.path.expanduser("~"), ".mythril"
@ -116,6 +150,12 @@ class SignatureDB(object):
"""
byte_sig = self._normalize_byte_sig(byte_sig)
# check if we have any Solidity signatures to look up
text_sigs = self.solidity_sigs.get(byte_sig)
if text_sigs is not None:
return text_sigs
# try lookup in the local DB
with SQLiteDB(self.path) as cur:
cur.execute("SELECT text_sig FROM signatures WHERE byte_sig=?", (byte_sig,))
@ -156,7 +196,6 @@ class SignatureDB(object):
:param file_path: solidity source code file path
:return:
"""
sigs = {}
cmd = [solc_binary, "--hashes", file_path]
if solc_args:
cmd.extend(solc_args.split())
@ -184,12 +223,16 @@ class SignatureDB(object):
for line in stdout:
# the ':' need not be checked but just to be sure
if all(map(lambda x: x in line, ["(", ")", ":"])):
sigs["0x" + line.split(":")[0]] = [line.split(":")[1].strip()]
solc_bytes = "0x" + line.split(":")[0]
solc_text = line.split(":")[1].strip()
self.solidity_sigs[solc_bytes].append(solc_text)
logging.debug("Signatures: found %d signatures after parsing" % len(sigs))
logging.debug(
"Signatures: found %d signatures after parsing" % len(self.solidity_sigs)
)
# update DB with what we've found
for byte_sig, text_sigs in sigs.items():
for byte_sig, text_sigs in self.solidity_sigs.items():
for text_sig in text_sigs:
self.add(byte_sig, text_sig)

@ -18,16 +18,6 @@ MYTHRIL_DIR = TESTS_DIR / "mythril_dir"
class BaseTestCase(TestCase):
def setUp(self):
self.changed_files = []
self.ori_mythril_dir = os.environ.get("MYTHRIL_DIR", "")
os.environ["MYTHRIL_DIR"] = str(MYTHRIL_DIR)
shutil.copyfile(
str(MYTHRIL_DIR / "signatures.db.example"),
str(MYTHRIL_DIR / "signatures.db"),
)
def tearDown(self):
os.environ["MYTHRIL_DIR"] = self.ori_mythril_dir
os.remove(str(MYTHRIL_DIR / "signatures.db"))
def compare_files_error_message(self):
message = "Following output files are changed, compare them manually to see differences: \n"

@ -1,4 +0,0 @@
[defaults]
leveldb_dir = /Users/bernhardmueller/Library/Ethereum/geth/chaindata
dynamic_loading = infura
Loading…
Cancel
Save