Refactor code

pending-opcodes
Eric N 5 years ago
parent 72db1237fb
commit 581c8d7b01
  1. 105
      mythril/laser/ethereum/instructions.py
  2. 3
      mythril/laser/ethereum/transaction/transaction_models.py

@ -787,7 +787,7 @@ class Instruction:
return [global_state] return [global_state]
@staticmethod @staticmethod
def _calldata_copy_helper(global_state, state, mstart, dstart, size): def _calldata_copy_helper(global_state, mstate, mstart, dstart, size):
environment = global_state.environment environment = global_state.environment
try: try:
@ -811,11 +811,11 @@ class Instruction:
size = cast(int, size) size = cast(int, size)
if size > 0: if size > 0:
try: try:
state.mem_extend(mstart, size) mstate.mem_extend(mstart, size)
except TypeError as e: except TypeError as e:
log.debug("Memory allocation error: {}".format(e)) log.debug("Memory allocation error: {}".format(e))
state.mem_extend(mstart, 1) mstate.mem_extend(mstart, 1)
state.memory[mstart] = global_state.new_bitvec( mstate.memory[mstart] = global_state.new_bitvec(
"calldata_" "calldata_"
+ str(environment.active_account.contract_name) + str(environment.active_account.contract_name)
+ "[" + "["
@ -840,12 +840,12 @@ class Instruction:
else simplify(cast(BitVec, i_data) + 1) else simplify(cast(BitVec, i_data) + 1)
) )
for i in range(len(new_memory)): for i in range(len(new_memory)):
state.memory[i + mstart] = new_memory[i] mstate.memory[i + mstart] = new_memory[i]
except IndexError: except IndexError:
log.debug("Exception copying calldata to memory") log.debug("Exception copying calldata to memory")
state.memory[mstart] = global_state.new_bitvec( mstate.memory[mstart] = global_state.new_bitvec(
"calldata_" "calldata_"
+ str(environment.active_account.contract_name) + str(environment.active_account.contract_name)
+ "[" + "["
@ -1039,34 +1039,6 @@ class Instruction:
global_state.mstate.stack.append(global_state.environment.gasprice) global_state.mstate.stack.append(global_state.environment.gasprice)
return [global_state] return [global_state]
@staticmethod
def _handle_symbolic_args(
global_state: GlobalState, concrete_memory_offset: int
) -> None:
"""
In contract creation transaction with dynamic arguments(like arrays, maps) solidity will try to
execute CODECOPY with code size as len(with_args) - len(without_args) which in our case
would be 0, hence we are writing 10 symbol words onto the memory on the assumption that
no one would use 10 array/map arguments for constructor.
:param global_state: The global state
:param concrete_memory_offset: The memory offset on which symbols should be written
"""
no_of_words = ceil(
min(len(global_state.environment.code.bytecode) / 2, 320) / 32
)
global_state.mstate.mem_extend(concrete_memory_offset, 32 * no_of_words)
for i in range(no_of_words):
global_state.mstate.memory.write_word_at(
concrete_memory_offset + i * 32,
global_state.new_bitvec(
"code_{}({})".format(
concrete_memory_offset + i * 32,
global_state.environment.active_account.contract_name,
),
256,
),
)
@StateTransition() @StateTransition()
def codecopy_(self, global_state: GlobalState) -> List[GlobalState]: def codecopy_(self, global_state: GlobalState) -> List[GlobalState]:
""" """
@ -1088,17 +1060,17 @@ class Instruction:
# Treat creation code after the expected disassembly as calldata. # Treat creation code after the expected disassembly as calldata.
# This is a slightly hacky way to ensure that symbolic constructor # This is a slightly hacky way to ensure that symbolic constructor
# arguments work correctly. # arguments work correctly.
mstate = global_state.mstate
offset = code_offset - code_size offset = code_offset - code_size
log.warning("Doing hacky thing offset: {} size: {}".format(offset, size)) log.debug("Copying from code offset: {} with size: {}".format(offset, size))
if isinstance(global_state.environment.calldata, SymbolicCalldata): if isinstance(global_state.environment.calldata, SymbolicCalldata):
if code_offset >= code_size: if code_offset >= code_size:
return self._calldata_copy_helper( return self._calldata_copy_helper(
global_state, global_state.mstate, memory_offset, offset, size global_state, mstate, memory_offset, offset, size
) )
else: else:
# Copy from both code and calldata appropriately. # Copy from both code and calldata appropriately.
state = global_state.mstate
environment = global_state.environment environment = global_state.environment
concrete_memory_offset = helper.get_concrete_int(memory_offset) concrete_memory_offset = helper.get_concrete_int(memory_offset)
concrete_code_offset = helper.get_concrete_int(code_offset) concrete_code_offset = helper.get_concrete_int(code_offset)
@ -1124,47 +1096,21 @@ class Instruction:
calldata_copy_size if calldata_copy_size >= 0 else 0 calldata_copy_size if calldata_copy_size >= 0 else 0
) )
try: [global_state] = self._code_copy_helper(
global_state.mstate.mem_extend( code=global_state.environment.code.bytecode,
concrete_memory_offset, concrete_size + calldata_copy_size memory_offset=memory_offset,
) code_offset=code_copy_offset,
except TypeError: size=code_copy_size,
global_state.mstate.mem_extend(concrete_memory_offset, 1) op="CODECOPY",
global_state.mstate.memory[ global_state=global_state,
concrete_memory_offset
] = global_state.new_bitvec(
"code({})".format(
global_state.environment.active_account.contract_name
),
8,
)
return [global_state]
for i in range(concrete_size):
if i < code_copy_size:
# copy from code
global_state.mstate.memory[concrete_memory_offset + i] = int(
code[
2
* (code_copy_offset + i) : 2
* (code_copy_offset + i + 1)
],
16,
) )
elif i < code_copy_size + calldata_copy_size: return self._calldata_copy_helper(
# copy from calldata global_state=global_state,
global_state.mstate.memory[ mstate=mstate,
concrete_memory_offset + i mstart=memory_offset + code_copy_size,
] = calldata[calldata_copy_offset + i - code_copy_size] dstart=calldata_copy_offset,
else: size=calldata_copy_size,
global_state.mstate.memory[
concrete_memory_offset + i
] = global_state.new_bitvec(
"code({})".format(
global_state.environment.active_account.contract_name
),
8,
) )
return [global_state]
return self._code_copy_helper( return self._code_copy_helper(
code=global_state.environment.code.bytecode, code=global_state.environment.code.bytecode,
@ -1254,13 +1200,6 @@ class Instruction:
if code[0:2] == "0x": if code[0:2] == "0x":
code = code[2:] code = code[2:]
if concrete_size == 0 and isinstance(
global_state.current_transaction, ContractCreationTransaction
):
if concrete_code_offset >= len(code) // 2:
Instruction._handle_symbolic_args(global_state, concrete_memory_offset)
return [global_state]
for i in range(concrete_size): for i in range(concrete_size):
if 2 * (concrete_code_offset + i + 1) <= len(code): if 2 * (concrete_code_offset + i + 1) <= len(code):
global_state.mstate.memory[concrete_memory_offset + i] = int( global_state.mstate.memory[concrete_memory_offset + i] = int(

@ -198,6 +198,9 @@ class ContractCreationTransaction(BaseTransaction):
contract_address=None, contract_address=None,
) -> None: ) -> None:
self.prev_world_state = deepcopy(world_state) self.prev_world_state = deepcopy(world_state)
contract_address = (
contract_address if isinstance(contract_address, int) else None
)
callee_account = world_state.create_account( callee_account = world_state.create_account(
0, concrete_storage=True, creator=caller.value, address=contract_address 0, concrete_storage=True, creator=caller.value, address=contract_address
) )

Loading…
Cancel
Save