From b30e70235c5004cc7490d1a570d0ea9c63b58e03 Mon Sep 17 00:00:00 2001 From: Joran Honig Date: Tue, 10 Jul 2018 17:03:47 +0200 Subject: [PATCH] Implement coverage measurement --- mythril/laser/ethereum/svm.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mythril/laser/ethereum/svm.py b/mythril/laser/ethereum/svm.py index 1ceb3740..943065ba 100644 --- a/mythril/laser/ethereum/svm.py +++ b/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.cfg import NodeFlags, Node, Edge, JumpType from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy +from functools import reduce TT256 = 2 ** 256 TT256M1 = 2 ** 256 - 1 @@ -23,6 +24,7 @@ class LaserEVM: Laser EVM class """ def __init__(self, accounts, dynamic_loader=None, max_depth=22): + self.instructions_covered = [] self.accounts = accounts self.nodes = {} @@ -51,7 +53,8 @@ class LaserEVM: 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) self.nodes[initial_node.uid] = initial_node @@ -63,6 +66,7 @@ class LaserEVM: self._sym_exec() 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) def _sym_exec(self): @@ -81,6 +85,7 @@ class LaserEVM: def execute_state(self, global_state): instructions = global_state.environment.code.instruction_list 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 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) 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