Modified codecopy. Debugging issue with contract function calls.

pending-opcodes
Eric N 5 years ago
parent 612fc4df34
commit a9755b8c67
  1. 2
      mythril/laser/ethereum/gas.py
  2. 171
      mythril/laser/ethereum/instructions.py

@ -180,7 +180,7 @@ OPCODE_GAS = {
"LOG3": (4 * 375, 4 * 375 + 8 * 32),
"LOG4": (5 * 375, 5 * 375 + 8 * 32),
"CREATE": (32000, 32000),
"CREATE2": (32000, 32000), # TODO: Make the gas value is dynamic
"CREATE2": (32000, 32000), # TODO: Make the gas values dynamic
"CALL": (700, 700 + 9000 + 25000),
"NATIVE_COST": calculate_native_gas,
"CALLCODE": (700, 700 + 9000 + 25000),

@ -50,6 +50,7 @@ from mythril.laser.ethereum.transaction import (
MessageCallTransaction,
TransactionStartSignal,
ContractCreationTransaction,
get_next_transaction_id,
)
from mythril.support.support_utils import get_code_hash
@ -939,13 +940,13 @@ class Instruction:
if isinstance(global_state.current_transaction, ContractCreationTransaction):
# Hacky way to ensure constructor arguments work - Pick some reasonably large size.
no_of_bytes = len(disassembly.bytecode) // 2
if isinstance(calldata, ConcreteCalldata):
no_of_bytes += calldata.size
else:
no_of_bytes += 0x200 # space for 16 32-byte arguments
global_state.mstate.constraints.append(
global_state.environment.calldata.size == no_of_bytes
)
# if isinstance(calldata, ConcreteCalldata):
# no_of_bytes += calldata.size + 5000
# else:
no_of_bytes += 0x200 # space for 16 32-byte arguments
# global_state.mstate.constraints.append(
# global_state.environment.calldata.size == no_of_bytes
# )
else:
no_of_bytes = len(disassembly.bytecode) // 2
@ -1096,7 +1097,6 @@ class Instruction:
global_state, global_state.mstate, memory_offset, offset, size
)
else:
# creation code and arguments may be in same object.
# Copy from both code and calldata appropriately.
state = global_state.mstate
environment = global_state.environment
@ -1105,80 +1105,67 @@ class Instruction:
concrete_size = helper.get_concrete_int(size)
calldata = global_state.environment.calldata
calldata_size = helper.get_concrete_int(calldata.size)
total_size = code_size + calldata_size
if concrete_size > 0:
# borrow some logic from codecopyhelper and calldatacopyhelper
try:
state.mem_extend(concrete_memory_offset, concrete_size)
except TypeError as e:
log.debug("Memory allocation error: {}".format(e))
state.mem_extend(concrete_memory_offset, 1)
state.memory[mstart] = global_state.new_bitvec(
"calldata_"
+ str(environment.active_account.contract_name)
+ "["
+ str(offset)
+ ": + "
+ str(concrete_size)
+ "]",
8,
code_copy_offset = concrete_code_offset
code_copy_size = (
concrete_size
if concrete_code_offset + concrete_size <= code_size
else code_size - concrete_code_offset
)
code_copy_size = code_copy_size if code_copy_size >= 0 else 0
calldata_copy_offset = (
concrete_code_offset - code_size
if concrete_code_offset - code_size > 0
else 0
)
calldata_copy_size = concrete_code_offset + concrete_size - code_size
calldata_copy_size = (
calldata_copy_size if calldata_copy_size >= 0 else 0
)
try:
global_state.mstate.mem_extend(
concrete_memory_offset, concrete_size + calldata_copy_size
)
except TypeError:
global_state.mstate.mem_extend(concrete_memory_offset, 1)
global_state.mstate.memory[
concrete_memory_offset
] = global_state.new_bitvec(
"code({})".format(
global_state.environment.active_account.contract_name
),
8,
)
return [global_state]
for i in range(code_copy_size + calldata_copy_size):
if i < code_copy_size:
global_state.mstate.memory[concrete_memory_offset + i] = int(
code[
2
* (code_copy_offset + i) : 2
* (code_copy_offset + i + 1)
],
16,
)
return [global_state]
try:
i_data = code_size
new_memory = []
for i in range(concrete_size):
if concrete_code_offset + i < code_size:
# copy from code
state.memory[concrete_memory_offset + i] = int(
code[
2
* (concrete_code_offset + i) : 2
* (concrete_code_offset + i + 1)
],
16,
)
elif concrete_code_offset + i < total_size:
# copy from calldata
value = environment.calldata[i_data]
new_memory.append(value)
i_data = (
i_data + 1
if isinstance(i_data, int)
else simplify(cast(BitVec, i_data) + 1)
)
else:
raise IndexError
if new_memory:
for i in range(len(new_memory)):
state.memory[i + mstart] = new_memory[i]
except IndexError:
log.debug("Exception copying code to memory")
state.memory[mstart] = global_state.new_bitvec(
"code_"
+ str(environment.active_account.contract_name)
+ "["
+ str(code_offset)
+ ": + "
+ str(concrete_size)
+ "]",
elif i < code_copy_size + calldata_copy_size:
# copy from calldata
global_state.mstate.memory[
concrete_memory_offset + i
] = calldata[calldata_copy_offset + i]
else:
global_state.mstate.memory[
concrete_memory_offset + i
] = global_state.new_bitvec(
"code({})".format(
global_state.environment.active_account.contract_name
),
8,
)
elif concrete_size == 0 and isinstance(
global_state.current_transaction, ContractCreationTransaction
):
if concrete_code_offset >= total_size:
Instruction._handle_symbolic_args(
global_state, concrete_memory_offset
)
return [global_state]
return self._code_copy_helper(
code=global_state.environment.code.bytecode,
memory_offset=memory_offset,
@ -1750,26 +1737,20 @@ class Instruction:
call_data = get_call_data(global_state, mem_offset, mem_offset + mem_size)
# code_raw = []
# code_end = call_data.size
# for i in range(call_data.size):
# # Proper way to delimit init_bytecode? Seems to work.
# if call_data[i].symbolic:
# code_end = i
# break
# code_raw.append(call_data[i].value)
call_data = call_data.concrete(None)
code_end = len(call_data)
for i in range(len(call_data)):
if not isinstance(call_data[i], int):
code_raw = []
code_end = call_data.size
for i in range(call_data.size):
if call_data[i].symbolic:
code_end = i
break
code_raw.append(call_data[i].value)
# code_str = bytes.hex(bytes(code_raw))
code_str = bytes.hex(bytes(call_data[0:code_end]))
code_str = bytes.hex(bytes(code_raw))
constructor_arguments = call_data[code_end:]
next_transaction_id = get_next_transaction_id()
constructor_arguments = ConcreteCalldata(
next_transaction_id, call_data[code_end:]
)
code = Disassembly(code_str)
caller = environment.active_account.address
@ -1838,7 +1819,7 @@ class Instruction:
@StateTransition()
def create2_post(self, global_state: GlobalState) -> List[GlobalState]:
addr, call_value, mem_offset, mem_size = global_state.mstate.pop(4)
addr, call_value, mem_offset, mem_size, salt = global_state.mstate.pop(5)
global_state.mstate.stack.append(addr)
return [global_state]

Loading…
Cancel
Save