mirror of https://github.com/ConsenSys/mythril
parent
00dc912f2c
commit
475ad946b8
@ -0,0 +1,58 @@ |
|||||||
|
from ethereum import utils |
||||||
|
from mythril.laser.smt import BitVec, Function, URem, symbol_factory, ULE, And, ULT, Or |
||||||
|
|
||||||
|
TOTAL_PARTS = 10 ** 40 |
||||||
|
PART = (2 ** 256 - 1) // TOTAL_PARTS |
||||||
|
INTERVAL_DIFFERENCE = 10 ** 30 |
||||||
|
|
||||||
|
|
||||||
|
class KeccakFunctionManager: |
||||||
|
def __init__(self): |
||||||
|
self.sizes = {} |
||||||
|
self.size_index = {} |
||||||
|
self.index_counter = TOTAL_PARTS - 34534 |
||||||
|
self.size_values = {} |
||||||
|
|
||||||
|
def create_keccak(self, data: BitVec, length: int): |
||||||
|
length = length * 8 |
||||||
|
assert length == data.size() |
||||||
|
try: |
||||||
|
func, inverse = self.sizes[length] |
||||||
|
except KeyError: |
||||||
|
func = Function("keccak256_{}".format(length), length, 256) |
||||||
|
inverse = Function("keccak256_{}-1".format(length), 256, length) |
||||||
|
self.sizes[length] = (func, inverse) |
||||||
|
self.size_values[length] = [] |
||||||
|
constraints = [] |
||||||
|
if data.symbolic is False: |
||||||
|
keccak = symbol_factory.BitVecVal( |
||||||
|
utils.sha3(data.value.to_bytes(length // 8, byteorder="big")), 256 |
||||||
|
) |
||||||
|
constraints.append(func(data) == keccak) |
||||||
|
|
||||||
|
constraints.append(inverse(func(data)) == data) |
||||||
|
if data.symbolic is False: |
||||||
|
return func(data), constraints |
||||||
|
|
||||||
|
constraints.append(URem(func(data), symbol_factory.BitVecVal(63, 256)) == 0) |
||||||
|
try: |
||||||
|
index = self.size_index[length] |
||||||
|
except KeyError: |
||||||
|
self.size_index[length] = self.index_counter |
||||||
|
index = self.index_counter |
||||||
|
self.index_counter -= INTERVAL_DIFFERENCE |
||||||
|
|
||||||
|
lower_bound = index * PART |
||||||
|
upper_bound = (index + 1) * PART |
||||||
|
|
||||||
|
condition = And( |
||||||
|
ULE(symbol_factory.BitVecVal(lower_bound, 256), func(data)), |
||||||
|
ULT(func(data), symbol_factory.BitVecVal(upper_bound, 256)), |
||||||
|
) |
||||||
|
for val in self.size_values[length]: |
||||||
|
condition = Or(condition, func(data) == val) |
||||||
|
constraints.append(condition) |
||||||
|
return func(data), constraints |
||||||
|
|
||||||
|
|
||||||
|
keccak_function_manager = KeccakFunctionManager() |
@ -0,0 +1,25 @@ |
|||||||
|
from typing import cast |
||||||
|
import z3 |
||||||
|
|
||||||
|
from mythril.laser.smt.bitvec import BitVec |
||||||
|
|
||||||
|
|
||||||
|
class Function: |
||||||
|
"""An uninterpreted function.""" |
||||||
|
|
||||||
|
def __init__(self, name: str, domain: int, value_range: int): |
||||||
|
"""Initializes an uninterpreted function. |
||||||
|
|
||||||
|
:param name: Name of the Function |
||||||
|
:param domain: The domain for the Function (10 -> all the values that a bv of size 10 could take) |
||||||
|
:param value_range: The range for the values of the function (10 -> all the values that a bv of size 10 could take) |
||||||
|
""" |
||||||
|
self.domain = z3.BitVecSort(domain) |
||||||
|
self.range = z3.BitVecSort(value_range) |
||||||
|
self.raw = z3.Function(name, self.domain, self.range) |
||||||
|
|
||||||
|
def __call__(self, item: BitVec) -> BitVec: |
||||||
|
"""Function accessor, item can be symbolic.""" |
||||||
|
return BitVec( |
||||||
|
cast(z3.BitVecRef, self.raw(item.raw)), annotations=item.annotations |
||||||
|
) # type: ignore |
Loading…
Reference in new issue