add per transaction coverage increase metrics

pull/986/head
Joran Honig 6 years ago
parent 1d8995402d
commit 0c6c9de851
  1. 40
      mythril/laser/ethereum/plugins/implementations/coverage.py

@ -21,6 +21,11 @@ class InstructionCoveragePlugin(LaserPlugin):
""" """
def __init__(self):
self.coverage = {} # type: Dict[str, Tuple[int, List[bool]]]
self.initial_coverage = 0
self.tx_id = 0
def initialize(self, symbolic_vm: LaserEVM): def initialize(self, symbolic_vm: LaserEVM):
"""Initializes the instruction coverage plugin """Initializes the instruction coverage plugin
@ -28,12 +33,14 @@ class InstructionCoveragePlugin(LaserPlugin):
:param symbolic_vm: :param symbolic_vm:
:return: :return:
""" """
coverage = {} # type: Dict[str, Tuple[int, List[bool]]] self.coverage = {}
self.initial_coverage = 0
self.tx_id = 0
@symbolic_vm.laser_hook("stop_sym_exec") @symbolic_vm.laser_hook("stop_sym_exec")
def stop_sym_exec_hook(): def stop_sym_exec_hook():
# Print results # Print results
for code, code_cov in coverage.items(): for code, code_cov in self.coverage.items():
cov_percentage = sum(code_cov[1]) / float(code_cov[0]) * 100 cov_percentage = sum(code_cov[1]) / float(code_cov[0]) * 100
log.info( log.info(
@ -47,13 +54,36 @@ class InstructionCoveragePlugin(LaserPlugin):
# Record coverage # Record coverage
code = global_state.environment.code.bytecode code = global_state.environment.code.bytecode
if code not in coverage.keys(): if code not in self.coverage.keys():
number_of_instructions = len( number_of_instructions = len(
global_state.environment.code.instruction_list global_state.environment.code.instruction_list
) )
coverage[code] = ( self.coverage[code] = (
number_of_instructions, number_of_instructions,
[False] * number_of_instructions, [False] * number_of_instructions,
) )
coverage[code][1][global_state.mstate.pc] = True self.coverage[code][1][global_state.mstate.pc] = True
@symbolic_vm.laser_hook("start_sym_trans")
def execute_start_sym_trans_hook():
self.initial_coverage = self._get_covered_instructions()
@symbolic_vm.laser_hook("stop_sym_trans")
def execute_stop_sym_trans_hook():
end_coverage = self._get_covered_instructions()
log.info(
"Number of new instructions covered in tx %d: %d"
% (self.tx_id, end_coverage - self.initial_coverage)
)
self.tx_id += 1
def _get_covered_instructions(self) -> int:
"""Gets the total number of covered instructions for all accounts in
the svm.
:return:
"""
total_covered_instructions = 0
for _, cv in self.coverage.items():
total_covered_instructions += sum(cv[1])
return total_covered_instructions

Loading…
Cancel
Save