Merge pull request #538 from JoranHonig/feature/invalidOpcode

Invalid opcode exception
pull/544/head
JoranHonig 6 years ago committed by GitHub
commit ef7257a1c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      mythril/laser/ethereum/evm_exceptions.py
  2. 12
      mythril/laser/ethereum/instructions.py
  3. 50
      mythril/laser/ethereum/svm.py

@ -12,3 +12,7 @@ class StackOverflowException(VmException):
class InvalidJumpDestination(VmException):
pass
class InvalidInstruction(VmException):
pass

@ -6,15 +6,16 @@ from ethereum import utils
from z3 import Extract, UDiv, simplify, Concat, ULT, UGT, BitVecNumRef, Not, \
is_false, is_expr, ExprRef, URem, SRem, BitVec, Solver, is_true, BitVecVal, If, BoolRef, Or
import mythril.laser.ethereum.natives as natives
import mythril.laser.ethereum.util as helper
from mythril.laser.ethereum import util
from mythril.laser.ethereum.call import get_call_parameters
from mythril.laser.ethereum.evm_exceptions import VmException, StackUnderflowException, InvalidJumpDestination, \
InvalidInstruction
from mythril.laser.ethereum.keccak import KeccakFunctionManager
from mythril.laser.ethereum.state import GlobalState, CalldataType
import mythril.laser.ethereum.natives as natives
from mythril.laser.ethereum.transaction import MessageCallTransaction, TransactionStartSignal, \
ContractCreationTransaction
from mythril.laser.ethereum.evm_exceptions import VmException, StackUnderflowException, InvalidJumpDestination
from mythril.laser.ethereum.keccak import KeccakFunctionManager
TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
@ -1004,11 +1005,12 @@ class Instruction:
@StateTransition()
def assert_fail_(self, global_state):
return []
# 0xfe: designated invalid opcode
raise InvalidInstruction
@StateTransition()
def invalid_(self, global_state):
return []
raise InvalidInstruction
@StateTransition()
def stop_(self, global_state):

@ -124,8 +124,19 @@ class LaserEVM:
new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(global_state)
except VmException as e:
logging.debug("Encountered a VmException, ending path: `{}`".format(str(e)))
new_global_states = []
transaction, return_global_state = global_state.transaction_stack.pop()
if return_global_state is None:
# In this case we don't put an unmodified world state in the open_states list Since in the case of an
# exceptional halt all changes should be discarded, and this world state would not provide us with a
# previously unseen world state
logging.debug("Encountered a VmException, ending path: `{}`".format(str(e)))
new_global_states = []
else:
# First execute the post hook for the transaction ending instruction
self._execute_post_hook(op_code, [global_state])
new_global_states = self._end_message_call(return_global_state, global_state,
revert_changes=True, return_data=None)
except TransactionStartSignal as e:
# Setup new global state
@ -149,25 +160,32 @@ class LaserEVM:
# First execute the post hook for the transaction ending instruction
self._execute_post_hook(op_code, [e.global_state])
# Resume execution of the transaction initializing instruction
op_code = return_global_state.environment.code.instruction_list[return_global_state.mstate.pc]['opcode']
new_global_states = self._end_message_call(return_global_state, global_state,
revert_changes=False, return_data=transaction.return_data)
# Set execution result in the return_state
return_global_state.last_return_data = transaction.return_data
return_global_state.world_state = copy(global_state.world_state)
return_global_state.environment.active_account = \
global_state.accounts[return_global_state.environment.active_account.address]
self._execute_post_hook(op_code, new_global_states)
# Execute the post instruction handler
new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(return_global_state, True)
return new_global_states, op_code
# In order to get a nice call graph we need to set the nodes here
for state in new_global_states:
state.node = global_state.node
def _end_message_call(self, return_global_state, global_state, revert_changes=False, return_data=None):
# Resume execution of the transaction initializing instruction
op_code = return_global_state.environment.code.instruction_list[return_global_state.mstate.pc]['opcode']
self._execute_post_hook(op_code, new_global_states)
# Set execution result in the return_state
return_global_state.last_return_data = return_data
if not revert_changes:
return_global_state.world_state = copy(global_state.world_state)
return_global_state.environment.active_account = \
global_state.accounts[return_global_state.environment.active_account.address]
return new_global_states, op_code
# Execute the post instruction handler
new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(return_global_state, True)
# In order to get a nice call graph we need to set the nodes here
for state in new_global_states:
state.node = global_state.node
return new_global_states
def _measure_coverage(self, global_state):
code = global_state.environment.code.bytecode

Loading…
Cancel
Save