Add global state split block

pull/897/head
Nikhil Parasaram 6 years ago
parent 06b708b49f
commit 2a2b4767fb
  1. 54
      mythril/laser/ethereum/instructions.py
  2. 9
      mythril/laser/ethereum/state/constraints.py
  3. 10
      mythril/laser/ethereum/state/global_state.py

@ -150,7 +150,6 @@ class Instruction:
if instruction_mutator is None: if instruction_mutator is None:
raise NotImplementedError raise NotImplementedError
return instruction_mutator(global_state) return instruction_mutator(global_state)
@StateTransition() @StateTransition()
@ -1089,47 +1088,54 @@ class Instruction:
simplify(Not(condition)) if type(condition) == BoolRef else condition == 0 simplify(Not(condition)) if type(condition) == BoolRef else condition == 0
) )
if (type(negated) == bool and negated) or ( # True case
type(negated) == BoolRef and not is_false(negated) condi = simplify(condition) if type(condition) == BoolRef else condition != 0
):
new_state = copy(global_state) # Get jump destination
index = util.get_instruction_index(disassembly.instruction_list, jump_addr)
negated_cond = (type(negated) == bool and negated) or ( type(negated) == BoolRef and not is_false(negated))
positive_cond = (type(condi) == bool and condi) or ( type(condi) == BoolRef and not is_false(condi) )
branched = False
if index and negated_cond and positive_cond:
new_state1, new_state2 = global_state.split_global_state()
else:
new_state1, new_state2 = copy(global_state), copy(global_state)
if negated_cond:
# add JUMPI gas cost # add JUMPI gas cost
new_state.mstate.min_gas_used += min_gas new_state1.mstate.min_gas_used += min_gas
new_state.mstate.max_gas_used += max_gas new_state1.mstate.max_gas_used += max_gas
# manually increment PC # manually increment PC
new_state.mstate.depth += 1 new_state1.mstate.depth += 1
new_state.mstate.pc += 1 new_state1.mstate.pc += 1
new_state.mstate.constraints.append(negated) new_state1.mstate.constraints.append(negated)
states.append(new_state) states.append(new_state1)
else: else:
logging.debug("Pruned unreachable states.") logging.debug("Pruned unreachable states.")
# True case # True case
# Get jump destination
index = util.get_instruction_index(disassembly.instruction_list, jump_addr)
if not index: if not index:
logging.debug("Invalid jump destination: " + str(jump_addr)) logging.debug("Invalid jump destination: " + str(jump_addr))
return states return states
instr = disassembly.instruction_list[index] instr = disassembly.instruction_list[index]
condi = simplify(condition) if type(condition) == BoolRef else condition != 0
if instr["opcode"] == "JUMPDEST": if instr["opcode"] == "JUMPDEST":
if (type(condi) == bool and condi) or ( if positive_cond:
type(condi) == BoolRef and not is_false(condi) new_state2 = copy(global_state)
):
new_state = copy(global_state)
# add JUMPI gas cost # add JUMPI gas cost
new_state.mstate.min_gas_used += min_gas new_state2.mstate.min_gas_used += min_gas
new_state.mstate.max_gas_used += max_gas new_state2.mstate.max_gas_used += max_gas
# manually set PC to destination # manually set PC to destination
new_state.mstate.pc = index new_state2.mstate.pc = index
new_state.mstate.depth += 1 new_state2.mstate.depth += 1
new_state.mstate.constraints.append(condi) new_state2.mstate.constraints.append(condi)
states.append(new_state) states.append(new_state2)
else: else:
logging.debug("Pruned unreachable states.") logging.debug("Pruned unreachable states.")
del global_state del global_state

@ -33,11 +33,10 @@ class Constraints(list):
def __copy__(self): def __copy__(self):
constraint_list = super(Constraints, self).copy() constraint_list = super(Constraints, self).copy()
if self.solver is not None: return Constraints(constraint_list, self.solver)
solver = copy(self.solver)
else: def copy_solver(self):
solver = None self.solver = copy(self.solver)
return Constraints(constraint_list, solver)
def __deepcopy__(self, memodict=None): def __deepcopy__(self, memodict=None):
return self.__copy__() return self.__copy__()

@ -75,3 +75,13 @@ class GlobalState:
def new_bitvec(self, name: str, size=256) -> BitVec: def new_bitvec(self, name: str, size=256) -> BitVec:
transaction_id = self.current_transaction.id transaction_id = self.current_transaction.id
return BitVec("{}_{}".format(transaction_id, name), size) return BitVec("{}_{}".format(transaction_id, name), size)
def split_global_state(self):
global_state1 = copy(self)
global_state2 = copy(self)
global_state1.mstate.constraints.copy_solver()
global_state2.mstate.constraints.copy_solver()
return global_state1, global_state2

Loading…
Cancel
Save