mirror of https://github.com/ConsenSys/mythril
commit
a3e3b77f9d
@ -0,0 +1,104 @@ |
||||
from typing import Union |
||||
from z3 import BitVecRef, Extract, BitVecVal, If, BoolRef, Z3Exception, simplify, Concat |
||||
|
||||
from mythril.laser.ethereum import util |
||||
|
||||
|
||||
class Memory: |
||||
def __init__(self): |
||||
self._memory = [] |
||||
|
||||
def __len__(self): |
||||
return len(self._memory) |
||||
|
||||
def extend(self, size): |
||||
self._memory.extend(bytearray(size)) |
||||
|
||||
def get_word_at(self, index: int) -> Union[int, BitVecRef]: |
||||
""" |
||||
Access a word from a specified memory index |
||||
:param index: integer representing the index to access |
||||
:return: 32 byte word at the specified index |
||||
""" |
||||
try: |
||||
return util.concrete_int_from_bytes( |
||||
bytes([util.get_concrete_int(b) for b in self[index : index + 32]]), 0 |
||||
) |
||||
except TypeError: |
||||
result = simplify( |
||||
Concat( |
||||
[ |
||||
b if isinstance(b, BitVecRef) else BitVecVal(b, 8) |
||||
for b in self[index : index + 32] |
||||
] |
||||
) |
||||
) |
||||
assert result.size() == 256 |
||||
return result |
||||
|
||||
def write_word_at( |
||||
self, index: int, value: Union[int, BitVecRef, bool, BoolRef] |
||||
) -> None: |
||||
""" |
||||
Writes a 32 byte word to memory at the specified index` |
||||
:param index: index to write to |
||||
:param value: the value to write to memory |
||||
""" |
||||
try: |
||||
# Attempt to concretize value |
||||
if isinstance(value, bool): |
||||
_bytes = ( |
||||
int(1).to_bytes(32, byteorder="big") |
||||
if value |
||||
else int(0).to_bytes(32, byteorder="big") |
||||
) |
||||
else: |
||||
_bytes = util.concrete_int_to_bytes(value) |
||||
assert len(_bytes) == 32 |
||||
self[index : index + 32] = _bytes |
||||
except (Z3Exception, AttributeError): # BitVector or BoolRef |
||||
if isinstance(value, BoolRef): |
||||
value_to_write = If(value, BitVecVal(1, 256), BitVecVal(0, 256)) |
||||
else: |
||||
value_to_write = value |
||||
assert value_to_write.size() == 256 |
||||
|
||||
for i in range(0, value_to_write.size(), 8): |
||||
self[index + 31 - (i // 8)] = Extract(i + 7, i, value_to_write) |
||||
|
||||
def __getitem__(self, item: Union[int, slice]) -> Union[BitVecRef, int, list]: |
||||
if isinstance(item, slice): |
||||
start, step, stop = item.start, item.step, item.stop |
||||
if start is None: |
||||
start = 0 |
||||
if stop is None: # 2**256 is just a bit too big |
||||
raise IndexError("Invalid Memory Slice") |
||||
if step is None: |
||||
step = 1 |
||||
return [self[i] for i in range(start, stop, step)] |
||||
|
||||
try: |
||||
return self._memory[item] |
||||
except IndexError: |
||||
return 0 |
||||
|
||||
def __setitem__(self, key: Union[int, slice], value: Union[BitVecRef, int, list]): |
||||
if isinstance(key, slice): |
||||
start, step, stop = key.start, key.step, key.stop |
||||
|
||||
if start is None: |
||||
start = 0 |
||||
if stop is None: |
||||
raise IndexError("Invalid Memory Slice") |
||||
if step is None: |
||||
step = 1 |
||||
|
||||
for i in range(0, stop - start, step): |
||||
self[start + i] = value[i] |
||||
|
||||
else: |
||||
if isinstance(value, int): |
||||
assert 0 <= value <= 0xFF |
||||
if isinstance(value, BitVecRef): |
||||
assert value.size() == 8 |
||||
self._memory[key] = value |
@ -1 +1,66 @@ |
||||
{"error": null, "issues": [{"address": 618, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The function `_function_0x141f32ff` uses callcode. Callcode does not persist sender or value over the call. Use delegatecall instead.", "function": "_function_0x141f32ff", "max_gas_used": 1141, "min_gas_used": 389, "swc-id": "111", "title": "Use of callcode", "type": "Warning"}, {"address": 626, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "max_gas_used": 35856, "min_gas_used": 1104, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "max_gas_used": 35919, "min_gas_used": 1167, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "_function_0xeea4c864", "max_gas_used": 1229, "min_gas_used": 477, "swc-id": "107", "title": "External call to user-supplied address", "type": "Warning"}, {"address": 1046, "contract": "Unknown", "debug": "<DEBUG-DATA>", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "max_gas_used": 35944, "min_gas_used": 1192, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} |
||||
{ |
||||
"error": null, |
||||
"issues": [ |
||||
{ |
||||
"address": 618, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The function `_function_0x141f32ff` uses callcode. Callcode does not persist sender or value over the call. Use delegatecall instead.", |
||||
"function": "_function_0x141f32ff", |
||||
"max_gas_used": 1141, |
||||
"min_gas_used": 389, |
||||
"swc-id": "111", |
||||
"title": "Use of callcode", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 626, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x141f32ff", |
||||
"max_gas_used": 35856, |
||||
"min_gas_used": 1104, |
||||
"swc-id": "104", |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 857, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0x9b58bc26", |
||||
"max_gas_used": 35913, |
||||
"min_gas_used": 1161, |
||||
"swc-id": "104", |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
}, |
||||
{ |
||||
"address": 1038, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", |
||||
"function": "_function_0xeea4c864", |
||||
"max_gas_used": 1223, |
||||
"min_gas_used": 471, |
||||
"swc-id": "107", |
||||
"title": "External call to user-supplied address", |
||||
"type": "Warning" |
||||
}, |
||||
{ |
||||
"address": 1046, |
||||
"contract": "Unknown", |
||||
"debug": "<DEBUG-DATA>", |
||||
"description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", |
||||
"function": "_function_0xeea4c864", |
||||
"max_gas_used": 35938, |
||||
"min_gas_used": 1186, |
||||
"swc-id": "104", |
||||
"title": "Unchecked CALL return value", |
||||
"type": "Informational" |
||||
} |
||||
], |
||||
"success": true |
||||
} |
||||
|
Loading…
Reference in new issue