Merge pull request #984 from ConsenSys/features/coverage_plugin

Implement instruction coverage as a plugin
pull/997/head
Nikhil Parasaram 6 years ago committed by GitHub
commit e861c35bd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 59
      mythril/laser/ethereum/plugins/implementations/coverage.py
  2. 8
      mythril/laser/ethereum/plugins/plugin_factory.py

@ -0,0 +1,59 @@
from mythril.laser.ethereum.svm import LaserEVM
from mythril.laser.ethereum.plugins.plugin import LaserPlugin
from mythril.laser.ethereum.state.global_state import GlobalState
from typing import Dict, Tuple, List
import logging
log = logging.getLogger(__name__)
class InstructionCoveragePlugin(LaserPlugin):
"""InstructionCoveragePlugin
This plugin measures the instruction coverage of mythril.
The instruction coverage is the ratio between the instructions that have been executed
and the total amount of instructions.
Note that with lazy constraint solving enabled that this metric will be "unsound" as
reachability will not be considered for the calculation of instruction coverage.
"""
def initialize(self, symbolic_vm: LaserEVM):
"""Initializes the instruction coverage plugin
Introduces hooks for each instruction
:param symbolic_vm:
:return:
"""
coverage = {} # type: Dict[str, Tuple[int, List[bool]]]
@symbolic_vm.laser_hook("stop_sym_exec")
def stop_sym_exec_hook():
# Print results
for code, code_cov in coverage.items():
cov_percentage = sum(code_cov[1]) / float(code_cov[0]) * 100
log.info(
"Achieved {:.2f}% coverage for code: {}".format(
cov_percentage, code
)
)
@symbolic_vm.laser_hook("execute_state")
def execute_state_hook(global_state: GlobalState):
# Record coverage
code = global_state.environment.code.bytecode
if code not in coverage.keys():
number_of_instructions = len(
global_state.environment.code.instruction_list
)
coverage[code] = (
number_of_instructions,
[False] * number_of_instructions,
)
coverage[code][1][global_state.mstate.pc] = True

@ -3,6 +3,9 @@ from mythril.laser.ethereum.plugins.implementations.benchmark import BenchmarkPl
from mythril.laser.ethereum.plugins.implementations.mutation_pruner import (
MutationPruner,
)
from mythril.laser.ethereum.plugins.implementations.coverage import (
InstructionCoveragePlugin,
)
class PluginFactory:
@ -17,3 +20,8 @@ class PluginFactory:
def build_mutation_pruner_plugin() -> LaserPlugin:
""" Creates an instance of the mutation pruner plugin"""
return MutationPruner()
@staticmethod
def build_instruction_coverage_plugin() -> LaserPlugin:
""" Creates an instance of the instruction coverage plugin"""
return InstructionCoveragePlugin()

Loading…
Cancel
Save