Merge pull request #1129 from ConsenSys/develop

Merge changes to dependency pruning
pull/1146/head
Bernhard Mueller 5 years ago committed by GitHub
commit 43386d537b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 42
      mythril/laser/ethereum/plugins/implementations/dependency_pruner.py

@ -150,6 +150,12 @@ class DependencyPruner(LaserPlugin):
:param target_location :param target_location
""" """
log.debug(
"Updating dependency map for path: {} with location: {}".format(
path, target_location
)
)
try: try:
for address in path: for address in path:
if address in self.dependency_map: if address in self.dependency_map:
@ -170,13 +176,17 @@ class DependencyPruner(LaserPlugin):
for address in path: for address in path:
self.protected_addresses.add(address) self.protected_addresses.add(address)
def wanna_execute(self, address: int, storage_write_cache) -> bool: def wanna_execute(self, address: int, annotation: DependencyAnnotation) -> bool:
"""Decide whether the basic block starting at 'address' should be executed. """Decide whether the basic block starting at 'address' should be executed.
:param address :param address
:param storage_write_cache :param storage_write_cache
""" """
storage_write_cache = annotation.get_storage_write_cache(self.iteration - 1)
# Execute the block if it's marked as "protected" or doesn't yet have an entry in the dependency map.
if address in self.protected_addresses or address not in self.dependency_map: if address in self.protected_addresses or address not in self.dependency_map:
return True return True
@ -187,6 +197,18 @@ class DependencyPruner(LaserPlugin):
for location in storage_write_cache: for location in storage_write_cache:
for dependency in dependencies: for dependency in dependencies:
# Is there a known read operation along this path that matches a write in the previous transaction?
try:
solver.get_model([location == dependency])
return True
except UnsatError:
continue
# Has the *currently executed* path been influenced by a write operation in the previous transaction?
for dependency in annotation.storage_loaded:
try: try:
solver.get_model([location == dependency]) solver.get_model([location == dependency])
return True return True
@ -216,27 +238,25 @@ class DependencyPruner(LaserPlugin):
@symbolic_vm.post_hook("JUMP") @symbolic_vm.post_hook("JUMP")
def jump_hook(state: GlobalState): def jump_hook(state: GlobalState):
address = state.get_current_instruction()["address"] address = state.get_current_instruction()["address"]
annotation = get_dependency_annotation(state)
_check_basic_block(address, annotation)
@symbolic_vm.pre_hook("JUMPDEST")
def jumpdest_hook(state: GlobalState):
address = state.get_current_instruction()["address"]
annotation = get_dependency_annotation(state) annotation = get_dependency_annotation(state)
annotation.path.append(address)
_check_basic_block(address, annotation) _check_basic_block(address, annotation)
@symbolic_vm.post_hook("JUMPI") @symbolic_vm.post_hook("JUMPI")
def jumpi_hook(state: GlobalState): def jumpi_hook(state: GlobalState):
address = state.get_current_instruction()["address"] address = state.get_current_instruction()["address"]
annotation = get_dependency_annotation(state) annotation = get_dependency_annotation(state)
annotation.path.append(address)
_check_basic_block(address, annotation) _check_basic_block(address, annotation)
@symbolic_vm.pre_hook("SSTORE") @symbolic_vm.pre_hook("SSTORE")
def sstore_hook(state: GlobalState): def sstore_hook(state: GlobalState):
annotation = get_dependency_annotation(state) annotation = get_dependency_annotation(state)
annotation.extend_storage_write_cache( annotation.extend_storage_write_cache(
self.iteration, state.mstate.stack[-1] self.iteration, state.mstate.stack[-1]
) )
@ -288,15 +308,11 @@ class DependencyPruner(LaserPlugin):
if self.iteration < 2: if self.iteration < 2:
return return
annotation.path.append(address) if self.wanna_execute(address, annotation):
if self.wanna_execute(
address, annotation.get_storage_write_cache(self.iteration - 1)
):
return return
else: else:
log.debug( log.debug(
"Skipping state: Storage slots {} not read in block at address {}".format( "Skipping state: Storage slots {} not read in block at address {}, function".format(
annotation.get_storage_write_cache(self.iteration - 1), address annotation.get_storage_write_cache(self.iteration - 1), address
) )
) )

Loading…
Cancel
Save