|
|
@ -52,6 +52,8 @@ from mythril.laser.ethereum.evm_exceptions import ( |
|
|
|
) |
|
|
|
) |
|
|
|
from mythril.laser.ethereum.instruction_data import get_opcode_gas, calculate_sha3_gas |
|
|
|
from mythril.laser.ethereum.instruction_data import get_opcode_gas, calculate_sha3_gas |
|
|
|
from mythril.laser.ethereum.state.global_state import GlobalState |
|
|
|
from mythril.laser.ethereum.state.global_state import GlobalState |
|
|
|
|
|
|
|
from mythril.laser.ethereum.state.return_data import ReturnData |
|
|
|
|
|
|
|
|
|
|
|
from mythril.laser.ethereum.transaction import ( |
|
|
|
from mythril.laser.ethereum.transaction import ( |
|
|
|
MessageCallTransaction, |
|
|
|
MessageCallTransaction, |
|
|
|
TransactionStartSignal, |
|
|
|
TransactionStartSignal, |
|
|
@ -1340,7 +1342,7 @@ class Instruction: |
|
|
|
for i in range(concrete_size): |
|
|
|
for i in range(concrete_size): |
|
|
|
global_state.mstate.memory[concrete_memory_offset + i] = ( |
|
|
|
global_state.mstate.memory[concrete_memory_offset + i] = ( |
|
|
|
global_state.last_return_data[concrete_return_offset + i] |
|
|
|
global_state.last_return_data[concrete_return_offset + i] |
|
|
|
if i < len(global_state.last_return_data) |
|
|
|
if i < global_state.last_return_data.size |
|
|
|
else 0 |
|
|
|
else 0 |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -1353,16 +1355,10 @@ class Instruction: |
|
|
|
:param global_state: |
|
|
|
:param global_state: |
|
|
|
:return: |
|
|
|
:return: |
|
|
|
""" |
|
|
|
""" |
|
|
|
if global_state.last_return_data is None: |
|
|
|
if global_state.last_return_data: |
|
|
|
log.debug( |
|
|
|
global_state.mstate.stack.append(global_state.last_return_data.size) |
|
|
|
"No last_return_data found, adding an unconstrained bitvec to the stack" |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
global_state.mstate.stack.append( |
|
|
|
|
|
|
|
global_state.new_bitvec("returndatasize", 256) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
else: |
|
|
|
else: |
|
|
|
global_state.mstate.stack.append(len(global_state.last_return_data)) |
|
|
|
global_state.mstate.stack.append(0) |
|
|
|
|
|
|
|
|
|
|
|
return [global_state] |
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
|
|
@StateTransition() |
|
|
|
@StateTransition() |
|
|
@ -1865,7 +1861,9 @@ class Instruction: |
|
|
|
state.mem_extend(offset, length) |
|
|
|
state.mem_extend(offset, length) |
|
|
|
StateTransition.check_gas_usage_limit(global_state) |
|
|
|
StateTransition.check_gas_usage_limit(global_state) |
|
|
|
return_data = state.memory[offset : offset + length] |
|
|
|
return_data = state.memory[offset : offset + length] |
|
|
|
global_state.current_transaction.end(global_state, return_data) |
|
|
|
global_state.current_transaction.end( |
|
|
|
|
|
|
|
global_state, ReturnData(return_data, length) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@StateTransition(is_state_mutation_instruction=True) |
|
|
|
@StateTransition(is_state_mutation_instruction=True) |
|
|
|
def selfdestruct_(self, global_state: GlobalState): |
|
|
|
def selfdestruct_(self, global_state: GlobalState): |
|
|
@ -1898,7 +1896,25 @@ class Instruction: |
|
|
|
""" |
|
|
|
""" |
|
|
|
state = global_state.mstate |
|
|
|
state = global_state.mstate |
|
|
|
offset, length = state.stack.pop(), state.stack.pop() |
|
|
|
offset, length = state.stack.pop(), state.stack.pop() |
|
|
|
return_data = [global_state.new_bitvec("return_data", 8)] |
|
|
|
if length.symbolic is False: |
|
|
|
|
|
|
|
return_data = [ |
|
|
|
|
|
|
|
global_state.new_bitvec( |
|
|
|
|
|
|
|
f"{global_state.current_transaction.id}_return_data_{i}", 8 |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
for i in range(length.value) |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
return_data = [ |
|
|
|
|
|
|
|
If( |
|
|
|
|
|
|
|
i < length, |
|
|
|
|
|
|
|
global_state.new_bitvec( |
|
|
|
|
|
|
|
f"{global_state.current_transaction.id}_return_data_{i}", 8 |
|
|
|
|
|
|
|
), |
|
|
|
|
|
|
|
0, |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
for i in range(300) |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
try: |
|
|
|
return_data = state.memory[ |
|
|
|
return_data = state.memory[ |
|
|
|
util.get_concrete_int(offset) : util.get_concrete_int(offset + length) |
|
|
|
util.get_concrete_int(offset) : util.get_concrete_int(offset + length) |
|
|
@ -1906,7 +1922,7 @@ class Instruction: |
|
|
|
except TypeError: |
|
|
|
except TypeError: |
|
|
|
log.debug("Return with symbolic length or offset. Not supported") |
|
|
|
log.debug("Return with symbolic length or offset. Not supported") |
|
|
|
global_state.current_transaction.end( |
|
|
|
global_state.current_transaction.end( |
|
|
|
global_state, return_data=return_data, revert=True |
|
|
|
global_state, return_data=ReturnData(return_data, length), revert=True |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@StateTransition() |
|
|
|
@StateTransition() |
|
|
@ -1947,13 +1963,27 @@ class Instruction: |
|
|
|
""" |
|
|
|
""" |
|
|
|
if memory_out_offset.symbolic is True or memory_out_size.symbolic is True: |
|
|
|
if memory_out_offset.symbolic is True or memory_out_size.symbolic is True: |
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
return_data = [] |
|
|
|
|
|
|
|
return_data_size = global_state.new_bitvec("returndatasize", 256) |
|
|
|
|
|
|
|
|
|
|
|
for i in range(memory_out_size.value): |
|
|
|
for i in range(memory_out_size.value): |
|
|
|
global_state.mstate.memory[memory_out_offset + i] = global_state.new_bitvec( |
|
|
|
data = global_state.new_bitvec( |
|
|
|
"call_output_var({})_{}".format( |
|
|
|
"call_output_var({})_{}".format( |
|
|
|
simplify(memory_out_offset + i), global_state.mstate.pc |
|
|
|
simplify(memory_out_offset + i), global_state.mstate.pc |
|
|
|
), |
|
|
|
), |
|
|
|
8, |
|
|
|
8, |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
return_data.append(data) |
|
|
|
|
|
|
|
for i in range(memory_out_size.value): |
|
|
|
|
|
|
|
global_state.mstate.memory[memory_out_offset + i] = If( |
|
|
|
|
|
|
|
i <= return_data_size, |
|
|
|
|
|
|
|
return_data[i], |
|
|
|
|
|
|
|
global_state.mstate.memory[memory_out_offset + i], |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
global_state.last_return_data = ReturnData( |
|
|
|
|
|
|
|
return_data=return_data, return_data_size=return_data_size |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@StateTransition() |
|
|
|
@StateTransition() |
|
|
|
def call_(self, global_state: GlobalState) -> List[GlobalState]: |
|
|
|
def call_(self, global_state: GlobalState) -> List[GlobalState]: |
|
|
@ -1982,6 +2012,9 @@ class Instruction: |
|
|
|
sender = environment.active_account.address |
|
|
|
sender = environment.active_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
|
|
|
|
self._write_symbolic_returndata( |
|
|
|
|
|
|
|
global_state, memory_out_offset, memory_out_size |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
@ -2072,6 +2105,9 @@ class Instruction: |
|
|
|
sender = global_state.environment.active_account.address |
|
|
|
sender = global_state.environment.active_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
|
|
|
|
self._write_symbolic_returndata( |
|
|
|
|
|
|
|
global_state, memory_out_offset, memory_out_size |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
@ -2176,9 +2212,9 @@ class Instruction: |
|
|
|
|
|
|
|
|
|
|
|
# Copy memory |
|
|
|
# Copy memory |
|
|
|
global_state.mstate.mem_extend( |
|
|
|
global_state.mstate.mem_extend( |
|
|
|
memory_out_offset, min(memory_out_size, len(global_state.last_return_data)) |
|
|
|
memory_out_offset, min(memory_out_size, global_state.last_return_data.size) |
|
|
|
) |
|
|
|
) |
|
|
|
for i in range(min(memory_out_size, len(global_state.last_return_data))): |
|
|
|
for i in range(min(memory_out_size, global_state.last_return_data.size)): |
|
|
|
global_state.mstate.memory[ |
|
|
|
global_state.mstate.memory[ |
|
|
|
i + memory_out_offset |
|
|
|
i + memory_out_offset |
|
|
|
] = global_state.last_return_data[i] |
|
|
|
] = global_state.last_return_data[i] |
|
|
@ -2216,6 +2252,9 @@ class Instruction: |
|
|
|
sender = global_state.environment.active_account.address |
|
|
|
sender = global_state.environment.active_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
|
|
|
|
self._write_symbolic_returndata( |
|
|
|
|
|
|
|
global_state, memory_out_offset, memory_out_size |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
@ -2317,9 +2356,9 @@ class Instruction: |
|
|
|
|
|
|
|
|
|
|
|
# Copy memory |
|
|
|
# Copy memory |
|
|
|
global_state.mstate.mem_extend( |
|
|
|
global_state.mstate.mem_extend( |
|
|
|
memory_out_offset, min(memory_out_size, len(global_state.last_return_data)) |
|
|
|
memory_out_offset, min(memory_out_size, global_state.last_return_data.size) |
|
|
|
) |
|
|
|
) |
|
|
|
for i in range(min(memory_out_size, len(global_state.last_return_data))): |
|
|
|
for i in range(min(memory_out_size, global_state.last_return_data.size)): |
|
|
|
global_state.mstate.memory[ |
|
|
|
global_state.mstate.memory[ |
|
|
|
i + memory_out_offset |
|
|
|
i + memory_out_offset |
|
|
|
] = global_state.last_return_data[i] |
|
|
|
] = global_state.last_return_data[i] |
|
|
@ -2356,10 +2395,13 @@ class Instruction: |
|
|
|
sender = environment.active_account.address |
|
|
|
sender = environment.active_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
receiver = callee_account.address |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
transfer_ether(global_state, sender, receiver, value) |
|
|
|
|
|
|
|
self._write_symbolic_returndata( |
|
|
|
|
|
|
|
global_state, memory_out_offset, memory_out_size |
|
|
|
|
|
|
|
) |
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.mstate.stack.append( |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
return [global_state] |
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
|
|
except ValueError as e: |
|
|
|
except ValueError as e: |
|
|
@ -2458,17 +2500,19 @@ class Instruction: |
|
|
|
) |
|
|
|
) |
|
|
|
return [global_state] |
|
|
|
return [global_state] |
|
|
|
|
|
|
|
|
|
|
|
# Copy memory |
|
|
|
|
|
|
|
global_state.mstate.mem_extend( |
|
|
|
global_state.mstate.mem_extend( |
|
|
|
memory_out_offset, min(memory_out_size, len(global_state.last_return_data)) |
|
|
|
memory_out_offset, min(memory_out_size, global_state.last_return_data.size) |
|
|
|
) |
|
|
|
) |
|
|
|
for i in range(min(memory_out_size, len(global_state.last_return_data))): |
|
|
|
|
|
|
|
|
|
|
|
for i in range(min(memory_out_size, global_state.last_return_data.size)): |
|
|
|
global_state.mstate.memory[ |
|
|
|
global_state.mstate.memory[ |
|
|
|
i + memory_out_offset |
|
|
|
i + memory_out_offset |
|
|
|
] = global_state.last_return_data[i] |
|
|
|
] = global_state.last_return_data[i] |
|
|
|
|
|
|
|
|
|
|
|
# Put return value on stack |
|
|
|
# Put return value on stack |
|
|
|
return_value = global_state.new_bitvec("retval_" + str(instr["address"]), 256) |
|
|
|
return_value = global_state.new_bitvec( |
|
|
|
|
|
|
|
"retval_" + str(global_state.get_current_instruction()["address"]), 256 |
|
|
|
|
|
|
|
) |
|
|
|
global_state.mstate.stack.append(return_value) |
|
|
|
global_state.mstate.stack.append(return_value) |
|
|
|
global_state.world_state.constraints.append(return_value == 1) |
|
|
|
global_state.world_state.constraints.append(return_value == 1) |
|
|
|
|
|
|
|
|
|
|
|