Implement coverage measurement

pull/331/head
Joran Honig 6 years ago
parent deb98df7c5
commit b30e70235c
  1. 12
      mythril/laser/ethereum/svm.py

@ -4,6 +4,7 @@ from mythril.laser.ethereum.state import GlobalState, Environment, CalldataType,
from mythril.laser.ethereum.instructions import Instruction from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType
from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy
from functools import reduce
TT256 = 2 ** 256 TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1 TT256M1 = 2 ** 256 - 1
@ -23,6 +24,7 @@ class LaserEVM:
Laser EVM class Laser EVM class
""" """
def __init__(self, accounts, dynamic_loader=None, max_depth=22): def __init__(self, accounts, dynamic_loader=None, max_depth=22):
self.instructions_covered = []
self.accounts = accounts self.accounts = accounts
self.nodes = {} self.nodes = {}
@ -51,7 +53,8 @@ class LaserEVM:
calldata_type=CalldataType.SYMBOLIC, calldata_type=CalldataType.SYMBOLIC,
) )
# TODO: contact name fix self.instructions_covered = [False for _ in environment.code.instruction_list]
initial_node = Node(environment.active_account.contract_name) initial_node = Node(environment.active_account.contract_name)
self.nodes[initial_node.uid] = initial_node self.nodes[initial_node.uid] = initial_node
@ -63,6 +66,7 @@ class LaserEVM:
self._sym_exec() self._sym_exec()
logging.info("Execution complete") logging.info("Execution complete")
logging.info("Achieved {0:.3g}% coverage".format(self.coverage))
logging.info("%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states) logging.info("%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states)
def _sym_exec(self): def _sym_exec(self):
@ -81,6 +85,7 @@ class LaserEVM:
def execute_state(self, global_state): def execute_state(self, global_state):
instructions = global_state.environment.code.instruction_list instructions = global_state.environment.code.instruction_list
op_code = instructions[global_state.mstate.pc]['opcode'] op_code = instructions[global_state.mstate.pc]['opcode']
self.instructions_covered[global_state.mstate.pc] = True
return Instruction(op_code, self.dynamic_loader).evaluate(global_state), op_code return Instruction(op_code, self.dynamic_loader).evaluate(global_state), op_code
def manage_cfg(self, opcode, new_states): def manage_cfg(self, opcode, new_states):
@ -130,3 +135,8 @@ class LaserEVM:
logging.info("- Entering function " + environment.active_account.contract_name + ":" + new_node.function_name) logging.info("- Entering function " + environment.active_account.contract_name + ":" + new_node.function_name)
new_node.function_name = environment.active_function_name new_node.function_name = environment.active_function_name
@property
def coverage(self):
return reduce(lambda sum, val: sum + 1 if val else sum, self.instructions_covered) / float(
len(self.instructions_covered)) * 100

Loading…
Cancel
Save