Merge pull request #1239 from ConsenSys/fix/iprof-ctrlc

Display instruction profiler results on ctrl+c or error
pull/1246/head
Nathan 5 years ago committed by GitHub
commit 3d1b0e889d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      mythril/analysis/symbolic.py
  2. 7
      mythril/laser/ethereum/svm.py
  3. 14
      mythril/mythril/mythril_analyzer.py

@ -4,6 +4,7 @@ purposes."""
from mythril.analysis.security import get_detection_module_hooks, get_detection_modules
from mythril.laser.ethereum import svm
from mythril.laser.ethereum.iprof import InstructionProfiler
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState
from mythril.laser.ethereum.strategy.basic import (
@ -28,7 +29,7 @@ from mythril.laser.ethereum.strategy.extensions.bounded_loops import (
BoundedLoopsStrategy,
)
from mythril.laser.smt import symbol_factory, BitVec
from typing import Union, List, Type
from typing import Union, List, Type, Optional
from mythril.solidity.soliditycontract import EVMContract, SolidityContract
from .ops import Call, VarType, get_variable
@ -44,32 +45,38 @@ class SymExecWrapper:
self,
contract,
address: Union[int, str, BitVec],
strategy,
strategy: str,
dynloader=None,
max_depth=22,
execution_timeout=None,
loop_bound=3,
create_timeout=None,
transaction_count=2,
max_depth: int = 22,
execution_timeout: Optional[int] = None,
loop_bound: int = 3,
create_timeout: Optional[int] = None,
transaction_count: int = 2,
modules=(),
compulsory_statespace=True,
enable_iprof=False,
disable_dependency_pruning=False,
run_analysis_modules=True,
enable_coverage_strategy=False,
custom_modules_directory="",
compulsory_statespace: bool = True,
iprof: Optional[InstructionProfiler] = None,
disable_dependency_pruning: bool = False,
run_analysis_modules: bool = True,
enable_coverage_strategy: bool = False,
custom_modules_directory: str = "",
):
"""
:param contract:
:param address:
:param strategy:
:param dynloader:
:param max_depth:
:param execution_timeout:
:param create_timeout:
:param transaction_count:
:param modules:
:param contract: Contract to symbolically execute
:param address: Address of the contract to symbolically execute
:param strategy: Execution strategy to use (bfs, dfs, etc)
:param dynloader: Dynamic Loader
:param max_depth: Max analysis depth
:param execution_timeout: Timeout for the entire analysis
:param create_timeout: Timeout for the creation transaction
:param transaction_count: Number of transactions to symbolically execute
:param modules: Analysis modules to run during analysis
:param compulsory_statespace: Boolean indicating whether or not the statespace should be saved
:param iprof: Instruction Profiler
:param disable_dependency_pruning: Boolean indicating whether dependency pruning should be disabled
:param run_analysis_modules: Boolean indicating whether analysis modules should be executed
:param enable_coverage_strategy: Boolean indicating whether the coverage strategy should be enabled
:param custom_modules_directory: The directory to read custom analysis modules from
"""
if isinstance(address, str):
address = symbol_factory.BitVecVal(int(address, 16), 256)
@ -116,7 +123,7 @@ class SymExecWrapper:
create_timeout=create_timeout,
transaction_count=transaction_count,
requires_statespace=requires_statespace,
enable_iprof=enable_iprof,
iprof=iprof,
enable_coverage_strategy=enable_coverage_strategy,
instruction_laser_plugin=instruction_laser_plugin,
)

@ -10,7 +10,6 @@ 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 VmException
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.iprof import InstructionProfiler
from mythril.laser.ethereum.plugins.signals import PluginSkipWorldState, PluginSkipState
from mythril.laser.ethereum.plugins.implementations.plugin_annotations import (
MutationAnnotation,
@ -58,7 +57,7 @@ class LaserEVM:
strategy=DepthFirstSearchStrategy,
transaction_count=2,
requires_statespace=True,
enable_iprof=False,
iprof=None,
enable_coverage_strategy=False,
instruction_laser_plugin=None,
) -> None:
@ -72,7 +71,7 @@ class LaserEVM:
:param strategy: Execution search strategy
:param transaction_count: The amount of transactions to execute
:param requires_statespace: Variable indicating whether the statespace should be recorded
:param enable_iprof: Variable indicating whether instruction profiling should be turned on
:param iprof: Instruction Profiler
"""
self.open_states = [] # type: List[WorldState]
@ -107,7 +106,7 @@ class LaserEVM:
self._start_sym_exec_hooks = [] # type: List[Callable]
self._stop_sym_exec_hooks = [] # type: List[Callable]
self.iprof = InstructionProfiler() if enable_iprof else None
self.iprof = iprof
if enable_coverage_strategy:
from mythril.laser.ethereum.plugins.implementations.coverage.coverage_strategy import (

@ -5,6 +5,7 @@ import logging
import traceback
from typing import Optional, List
from mythril.laser.ethereum.iprof import InstructionProfiler
from . import MythrilDisassembler
from mythril.support.source_support import Source
from mythril.support.loader import DynLoader
@ -61,7 +62,7 @@ class MythrilAnalyzer:
self.execution_timeout = execution_timeout
self.loop_bound = loop_bound
self.create_timeout = create_timeout
self.enable_iprof = enable_iprof
self.iprof = InstructionProfiler() if enable_iprof else None
self.disable_dependency_pruning = disable_dependency_pruning
self.enable_coverage_strategy = enable_coverage_strategy
self.custom_modules_directory = custom_modules_directory
@ -87,7 +88,7 @@ class MythrilAnalyzer:
max_depth=self.max_depth,
execution_timeout=self.execution_timeout,
create_timeout=self.create_timeout,
enable_iprof=self.enable_iprof,
iprof=self.iprof,
disable_dependency_pruning=self.disable_dependency_pruning,
run_analysis_modules=False,
enable_coverage_strategy=self.enable_coverage_strategy,
@ -111,6 +112,7 @@ class MythrilAnalyzer:
:param transaction_count: The amount of transactions to be executed
:return: The generated graph in html format
"""
sym = SymExecWrapper(
contract or self.contracts[0],
self.address,
@ -124,7 +126,7 @@ class MythrilAnalyzer:
execution_timeout=self.execution_timeout,
transaction_count=transaction_count,
create_timeout=self.create_timeout,
enable_iprof=self.enable_iprof,
iprof=self.iprof,
disable_dependency_pruning=self.disable_dependency_pruning,
run_analysis_modules=False,
enable_coverage_strategy=self.enable_coverage_strategy,
@ -164,7 +166,7 @@ class MythrilAnalyzer:
transaction_count=transaction_count,
modules=modules,
compulsory_statespace=False,
enable_iprof=self.enable_iprof,
iprof=self.iprof,
disable_dependency_pruning=self.disable_dependency_pruning,
enable_coverage_strategy=self.enable_coverage_strategy,
custom_modules_directory=self.custom_modules_directory,
@ -172,6 +174,8 @@ class MythrilAnalyzer:
issues = fire_lasers(sym, modules, self.custom_modules_directory)
except KeyboardInterrupt:
log.critical("Keyboard Interrupt")
if self.iprof is not None:
log.info("Instruction Statistics:\n{}".format(self.iprof))
issues = retrieve_callback_issues(
modules, self.custom_modules_directory
)
@ -184,6 +188,8 @@ class MythrilAnalyzer:
modules, self.custom_modules_directory
)
exceptions.append(traceback.format_exc())
if self.iprof is not None:
log.info("Instruction Statistics:\n{}".format(self.iprof))
for issue in issues:
issue.add_code_info(contract)

Loading…
Cancel
Save