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