Merge branch 'develop' into enhance/604

pull/897/head
JoranHonig 6 years ago committed by GitHub
commit a877f62960
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      mythril/alarm.py
  2. 7
      mythril/analysis/solver.py
  3. 7
      mythril/analysis/traceexplore.py
  4. 4
      mythril/exceptions.py
  5. 49
      mythril/laser/ethereum/svm.py
  6. 18
      mythril/laser/ethereum/time_handler.py
  7. 1
      mythril/laser/smt/bool.py
  8. 1
      mythril/laser/smt/solver.py
  9. 7
      mythril/mythril.py
  10. 20
      mythril/support/support_utils.py
  11. 2
      mythril/version.py
  12. 2
      requirements.txt
  13. 2
      setup.py
  14. 5
      tests/laser/transaction/create_transaction_test.py

@ -1,25 +0,0 @@
import signal
from types import FrameType
from mythril.exceptions import OutOfTimeError
def sigalrm_handler(signum: int, frame: FrameType) -> None:
raise OutOfTimeError
def start_timeout(timeout: int) -> None:
"""
Starts a timeout
:param timeout: Time in seconds to set the timeout for
:return: None
"""
signal.signal(signal.SIGALRM, sigalrm_handler)
signal.alarm(timeout)
def disable_timeout() -> None:
"""
Ensures that the timeout is disabled
:return: None
"""
signal.alarm(0)

@ -3,6 +3,7 @@ from z3 import sat, unknown, FuncInterp
import z3 import z3
from mythril.laser.smt import simplify, UGE, Optimize, symbol_factory from mythril.laser.smt import simplify, UGE, Optimize, symbol_factory
from mythril.laser.ethereum.time_handler import time_handler
from mythril.exceptions import UnsatError from mythril.exceptions import UnsatError
from mythril.laser.ethereum.transaction.transaction_models import ( from mythril.laser.ethereum.transaction.transaction_models import (
ContractCreationTransaction, ContractCreationTransaction,
@ -21,8 +22,10 @@ def get_model(constraints, minimize=(), maximize=()):
:return: :return:
""" """
s = Optimize() s = Optimize()
s.set_timeout(100000) timeout = min(100000, time_handler.time_remaining() - 500)
if timeout <= 0:
raise UnsatError
s.set_timeout(timeout)
for constraint in constraints: for constraint in constraints:
if type(constraint) == bool and not constraint: if type(constraint) == bool and not constraint:
raise UnsatError raise UnsatError

@ -97,7 +97,7 @@ def get_serializable_statespace(statespace):
account["balance"] = str(account["balance"]) account["balance"] = str(account["balance"])
storage = {} storage = {}
for storage_key in account["storage"]: for storage_key in account["storage"].keys():
storage[str(storage_key)] = str(account["storage"][storage_key]) storage[str(storage_key)] = str(account["storage"][storage_key])
state_accounts.append({"address": key, "storage": storage}) state_accounts.append({"address": key, "storage": storage})
@ -110,7 +110,10 @@ def get_serializable_statespace(statespace):
for state in states: for state in states:
state["machine"]["stack"] = [str(s) for s in state["machine"]["stack"]] state["machine"]["stack"] = [str(s) for s in state["machine"]["stack"]]
state["machine"]["memory"] = [str(m) for m in state["machine"]["memory"]] state["machine"]["memory"] = [
str(m)
for m in state["machine"]["memory"][: len(state["machine"]["memory"])]
]
truncated_code = truncated_code.replace("\\n", "\n") truncated_code = truncated_code.replace("\\n", "\n")
code = code.replace("\\n", "\n") code = code.replace("\\n", "\n")

@ -7,10 +7,6 @@ class MythrilBaseException(Exception):
pass pass
class OutOfTimeError(MythrilBaseException):
pass
class CompilerError(MythrilBaseException): class CompilerError(MythrilBaseException):
"""A Mythril exception denoting an error during code compilation.""" """A Mythril exception denoting an error during code compilation."""

@ -6,8 +6,6 @@ from datetime import datetime, timedelta
from functools import reduce from functools import reduce
from typing import Callable, Dict, List, Tuple, Union from typing import Callable, Dict, List, Tuple, Union
from mythril import alarm
from mythril.exceptions import OutOfTimeError
from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType
from mythril.laser.ethereum.evm_exceptions import StackUnderflowException from mythril.laser.ethereum.evm_exceptions import StackUnderflowException
from mythril.laser.ethereum.evm_exceptions import VmException from mythril.laser.ethereum.evm_exceptions import VmException
@ -16,6 +14,7 @@ from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.global_state import GlobalState from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy
from mythril.laser.ethereum.time_handler import time_handler
from mythril.laser.ethereum.plugins.signals import PluginSignal, PluginSkipWorldState from mythril.laser.ethereum.plugins.signals import PluginSignal, PluginSkipWorldState
from mythril.laser.ethereum.transaction import ( from mythril.laser.ethereum.transaction import (
ContractCreationTransaction, ContractCreationTransaction,
@ -120,36 +119,30 @@ class LaserEVM:
""" """
log.debug("Starting LASER execution") log.debug("Starting LASER execution")
try: time_handler.start_execution(self.execution_timeout)
alarm.start_timeout(self.execution_timeout) self.time = datetime.now()
self.time = datetime.now()
if main_address: if main_address:
log.info("Starting message call transaction to {}".format(main_address)) log.info("Starting message call transaction to {}".format(main_address))
self._execute_transactions(main_address) self._execute_transactions(main_address)
elif creation_code: elif creation_code:
log.info("Starting contract creation transaction") log.info("Starting contract creation transaction")
created_account = execute_contract_creation( created_account = execute_contract_creation(
self, creation_code, contract_name self, creation_code, contract_name
)
log.info(
"Finished contract creation, found {} open states".format(
len(self.open_states)
) )
log.info( )
"Finished contract creation, found {} open states".format( if len(self.open_states) == 0:
len(self.open_states) log.warning(
) "No contract was created during the execution of contract creation "
"Increase the resources for creation execution (--max-depth or --create-timeout)"
) )
if len(self.open_states) == 0:
log.warning( self._execute_transactions(created_account.address)
"No contract was created during the execution of contract creation "
"Increase the resources for creation execution (--max-depth or --create-timeout)"
)
self._execute_transactions(created_account.address)
except OutOfTimeError:
log.warning("Timeout occurred, ending symbolic execution")
finally:
alarm.disable_timeout()
log.info("Finished symbolic execution") log.info("Finished symbolic execution")
if self.requires_statespace: if self.requires_statespace:

@ -0,0 +1,18 @@
import time
from mythril.support.support_utils import Singleton
class TimeHandler(object, metaclass=Singleton):
def __init__(self):
self._start_time = None
self._execution_time = None
def start_execution(self, execution_time):
self._start_time = int(time.time() * 1000)
self._execution_time = execution_time * 1000
def time_remaining(self):
return self._execution_time - (int(time.time() * 1000) - self._start_time)
time_handler = TimeHandler()

@ -84,6 +84,7 @@ class Bool(Expression[z3.BoolRef]):
def And(*args: Bool) -> Bool: def And(*args: Bool) -> Bool:
"""Create an And expression.""" """Create an And expression."""
union = [] union = []
args = [arg if isinstance(arg, Bool) else Bool(arg) for arg in args]
for arg in args: for arg in args:
union.append(arg.annotations) union.append(arg.annotations)
return Bool(z3.And([a.raw for a in args]), union) return Bool(z3.And([a.raw for a in args]), union)

@ -20,6 +20,7 @@ class BaseSolver(Generic[T]):
:param timeout: :param timeout:
""" """
assert timeout > 0 # timeout <= 0 isn't supported by z3
self.raw.set(timeout=timeout) self.raw.set(timeout=timeout)
def add(self, constraints: Union[Bool, List[Bool]]) -> None: def add(self, constraints: Union[Bool, List[Bool]]) -> None:

@ -19,17 +19,10 @@ import solc
from ethereum import utils from ethereum import utils
from solc.exceptions import SolcError from solc.exceptions import SolcError
from mythril.analysis.callgraph import generate_graph
from mythril.analysis.report import Report
from mythril.analysis.security import fire_lasers
from mythril.analysis.symbolic import SymExecWrapper
from mythril.analysis.traceexplore import get_serializable_statespace
from mythril.ethereum import util from mythril.ethereum import util
from mythril.ethereum.evmcontract import EVMContract from mythril.ethereum.evmcontract import EVMContract
from mythril.ethereum.interface.leveldb.client import EthLevelDB
from mythril.ethereum.interface.rpc.client import EthJsonRpc from mythril.ethereum.interface.rpc.client import EthJsonRpc
from mythril.ethereum.interface.rpc.exceptions import ConnectionError from mythril.ethereum.interface.rpc.exceptions import ConnectionError
from mythril.exceptions import CompilerError, CriticalError, NoContractFoundError
from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file
from mythril.support import signatures from mythril.support import signatures
from mythril.support.source_support import Source from mythril.support.source_support import Source

@ -1 +1,21 @@
"""This module contains utility functions for the Mythril support package.""" """This module contains utility functions for the Mythril support package."""
class Singleton(type):
"""A metaclass type implementing the singleton pattern."""
_instances = {}
def __call__(cls, *args, **kwargs):
"""Delegate the call to an existing resource or a a new one.
This is not thread- or process-safe by default. It must be protected with
a lock.
:param args:
:param kwargs:
:return:
"""
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

@ -4,4 +4,4 @@ This file is suitable for sourcing inside POSIX shell, e.g. bash as well
as for importing into Python. as for importing into Python.
""" """
VERSION = "v0.19.11" # NOQA VERSION = "v0.20.0" # NOQA

@ -25,5 +25,5 @@ pytest_mock
requests requests
rlp>=1.0.1 rlp>=1.0.1
transaction>=2.2.1 transaction>=2.2.1
z3-solver>=4.8.0.0 z3-solver-mythril>=4.8.4.1
pysha3 pysha3

@ -75,7 +75,7 @@ setup(
"coloredlogs>=10.0", "coloredlogs>=10.0",
"py_ecc==1.4.2", "py_ecc==1.4.2",
"ethereum>=2.3.2", "ethereum>=2.3.2",
"z3-solver>=4.8.0.0", "z3-solver-mythril>=4.8.4.1",
"requests", "requests",
"py-solc", "py-solc",
"plyvel", "plyvel",

@ -41,7 +41,10 @@ def test_sym_exec():
) )
sym = SymExecWrapper( sym = SymExecWrapper(
contract, address=(util.get_indexed_address(0)), strategy="dfs" contract,
address=(util.get_indexed_address(0)),
strategy="dfs",
execution_timeout=10,
) )
issues = fire_lasers(sym) issues = fire_lasers(sym)

Loading…
Cancel
Save