Merge pull request #1411 from ConsenSys/feature/execution_info

Execution info
pull/1417/head
JoranHonig 4 years ago committed by GitHub
commit 727d5f3049
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      mythril/analysis/report.py
  2. 5
      mythril/analysis/symbolic.py
  3. 4
      mythril/laser/ethereum/svm.py
  4. 11
      mythril/laser/execution_info.py
  5. 10
      mythril/mythril/mythril_analyzer.py
  6. 5
      tests/mythril/mythril_analyzer_test.py

@ -3,9 +3,10 @@ import logging
import json import json
import operator import operator
from jinja2 import PackageLoader, Environment from jinja2 import PackageLoader, Environment
from typing import Dict, List from typing import Dict, List, Any, Optional
import hashlib import hashlib
from mythril.laser.execution_info import ExecutionInfo
from mythril.solidity.soliditycontract import SolidityContract from mythril.solidity.soliditycontract import SolidityContract
from mythril.analysis.swc_data import SWC_TO_TITLE from mythril.analysis.swc_data import SWC_TO_TITLE
from mythril.support.source_support import Source from mythril.support.source_support import Source
@ -184,18 +185,24 @@ class Report:
loader=PackageLoader("mythril.analysis"), trim_blocks=True loader=PackageLoader("mythril.analysis"), trim_blocks=True
) )
def __init__(self, contracts=None, exceptions=None): def __init__(
self,
contracts=None,
exceptions=None,
execution_info: Optional[List[ExecutionInfo]] = None,
):
""" """
:param contracts: :param contracts:
:param exceptions: :param exceptions:
""" """
self.issues = {} self.issues = {} # type: Dict[bytes, Issue]
self.solc_version = "" self.solc_version = ""
self.meta = {} self.meta = {} # type: Dict[str, Any]
self.source = Source() self.source = Source()
self.source.get_source_from_contracts_list(contracts) self.source.get_source_from_contracts_list(contracts)
self.exceptions = exceptions or [] self.exceptions = exceptions or []
self.execution_info = execution_info or []
def sorted_issues(self): def sorted_issues(self):
""" """
@ -246,6 +253,7 @@ class Report:
:return: :return:
""" """
# Setup issues
_issues = [] _issues = []
for key, issue in self.issues.items(): for key, issue in self.issues.items():
@ -272,7 +280,17 @@ class Report:
"extra": extra, "extra": extra,
} }
) )
meta_data = self._get_exception_data() # Setup meta
meta_data = self.meta
# Add logs to meta
meta_data.update(self._get_exception_data())
# Add execution info to meta
meta_data["mythril_execution_info"] = {}
for execution_info in self.execution_info:
meta_data["mythril_execution_info"].update(execution_info.as_dict())
result = [ result = [
{ {
"issues": _issues, "issues": _issues,

@ -2,6 +2,7 @@
purposes.""" purposes."""
from mythril.analysis.module import EntryPoint, ModuleLoader, get_detection_module_hooks from mythril.analysis.module import EntryPoint, ModuleLoader, get_detection_module_hooks
from mythril.laser.execution_info import ExecutionInfo
from mythril.laser.ethereum import svm from mythril.laser.ethereum import svm
from mythril.laser.ethereum.state.account import Account from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.world_state import WorldState from mythril.laser.ethereum.state.world_state import WorldState
@ -300,3 +301,7 @@ class SymExecWrapper:
) )
state_index += 1 state_index += 1
@property
def execution_info(self) -> List[ExecutionInfo]:
return self.laser.execution_info

@ -7,6 +7,7 @@ from typing import Callable, Dict, DefaultDict, List, Tuple, Optional
from mythril.support.opcodes import opcodes as OPCODES from mythril.support.opcodes import opcodes as OPCODES
from mythril.analysis.potential_issues import check_potential_issues from mythril.analysis.potential_issues import check_potential_issues
from mythril.laser.execution_info import ExecutionInfo
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
@ -72,8 +73,9 @@ class LaserEVM:
:param requires_statespace: Variable indicating whether the statespace should be recorded :param requires_statespace: Variable indicating whether the statespace should be recorded
:param iprof: Instruction Profiler :param iprof: Instruction Profiler
""" """
self.open_states = [] # type: List[WorldState] self.execution_info = [] # type: List[ExecutionInfo]
self.open_states = [] # type: List[WorldState]
self.total_states = 0 self.total_states = 0
self.dynamic_loader = dynamic_loader self.dynamic_loader = dynamic_loader

@ -0,0 +1,11 @@
from abc import ABC, abstractmethod
class ExecutionInfo(ABC):
@abstractmethod
def as_dict(self):
"""Returns a dictionary with the execution info contained in this object
The returned dictionary only uses primitive types.
"""
pass

@ -19,6 +19,7 @@ from mythril.ethereum.evmcontract import EVMContract
from mythril.laser.smt import SolverStatistics from mythril.laser.smt import SolverStatistics
from mythril.support.start_time import StartTime from mythril.support.start_time import StartTime
from mythril.exceptions import DetectorNotFoundError from mythril.exceptions import DetectorNotFoundError
from mythril.laser.execution_info import ExecutionInfo
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -139,6 +140,7 @@ class MythrilAnalyzer:
all_issues = [] # type: List[Issue] all_issues = [] # type: List[Issue]
SolverStatistics().enabled = True SolverStatistics().enabled = True
exceptions = [] exceptions = []
execution_info = None # type: Optional[List[ExecutionInfo]]
for contract in self.contracts: for contract in self.contracts:
StartTime() # Reinitialize start time for new contracts StartTime() # Reinitialize start time for new contracts
try: try:
@ -158,6 +160,7 @@ class MythrilAnalyzer:
custom_modules_directory=self.custom_modules_directory, custom_modules_directory=self.custom_modules_directory,
) )
issues = fire_lasers(sym, modules) issues = fire_lasers(sym, modules)
execution_info = sym.execution_info
except DetectorNotFoundError as e: except DetectorNotFoundError as e:
# Bubble up # Bubble up
raise e raise e
@ -179,8 +182,13 @@ class MythrilAnalyzer:
source_data = Source() source_data = Source()
source_data.get_source_from_contracts_list(self.contracts) source_data.get_source_from_contracts_list(self.contracts)
# Finally, output the results # Finally, output the results
report = Report(contracts=self.contracts, exceptions=exceptions) report = Report(
contracts=self.contracts,
exceptions=exceptions,
execution_info=execution_info,
)
for issue in all_issues: for issue in all_issues:
report.append_issue(issue) report.append_issue(issue)

@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
from mythril.mythril import MythrilDisassembler, MythrilAnalyzer from mythril.mythril import MythrilDisassembler, MythrilAnalyzer
from mythril.analysis.report import Issue from mythril.analysis.report import Issue
from mock import patch from mock import patch, PropertyMock
@patch("mythril.analysis.report.Issue.add_code_info", return_value=None) @patch("mythril.analysis.report.Issue.add_code_info", return_value=None)
@ -9,8 +9,9 @@ from mock import patch
"mythril.mythril.mythril_analyzer.fire_lasers", "mythril.mythril.mythril_analyzer.fire_lasers",
return_value=[Issue("", "", "234", "101", "title", "0x02445")], return_value=[Issue("", "", "234", "101", "title", "0x02445")],
) )
@patch("mythril.mythril.mythril_analyzer.SymExecWrapper", return_value=None) @patch("mythril.mythril.mythril_analyzer.SymExecWrapper")
def test_fire_lasers(mock_sym, mock_fire_lasers, mock_code_info): def test_fire_lasers(mock_sym, mock_fire_lasers, mock_code_info):
type(mock_sym.return_value).execution_info = PropertyMock(return_value=[])
disassembler = MythrilDisassembler(eth=None) disassembler = MythrilDisassembler(eth=None)
disassembler.load_from_solidity( disassembler.load_from_solidity(
[ [

Loading…
Cancel
Save