@ -5,16 +5,15 @@ from z3 import (
BitVecRef ,
BitVecRef ,
BitVecNumRef ,
BitVecNumRef ,
BitVecSort ,
BitVecSort ,
Solver ,
ExprRef ,
ExprRef ,
Concat ,
Concat ,
sat ,
sat ,
simplify ,
simplify ,
Array ,
Array ,
ForAll ,
ForAll ,
Solver ,
UGT ,
Implies ,
Implies ,
UGE ,
UGT ,
)
)
from z3 . z3types import Z3Exception
from z3 . z3types import Z3Exception
from mythril . disassembler . disassembly import Disassembly
from mythril . disassembler . disassembly import Disassembly
@ -46,7 +45,7 @@ class Calldata:
: param starting_calldata : byte array representing the concrete calldata of a transaction
: param starting_calldata : byte array representing the concrete calldata of a transaction
"""
"""
self . tx_id = tx_id
self . tx_id = tx_id
if starting_calldata :
if not starting_calldata is None :
self . _calldata = [ ]
self . _calldata = [ ]
self . calldatasize = BitVecVal ( len ( starting_calldata ) , 256 )
self . calldatasize = BitVecVal ( len ( starting_calldata ) , 256 )
self . concrete = True
self . concrete = True
@ -57,32 +56,21 @@ class Calldata:
self . calldatasize = BitVec ( " {} _calldatasize " . format ( self . tx_id ) , 256 )
self . calldatasize = BitVec ( " {} _calldatasize " . format ( self . tx_id ) , 256 )
self . concrete = False
self . concrete = False
self . starting_calldata = starting_calldata or [ ]
@property
def constraints ( self ) :
constraints = [ ]
if self . concrete :
if self . concrete :
for calldata_byte in self . starting_calldata :
for calldata_byte in starting_calldata :
if type ( calldata_byte ) == int :
if type ( calldata_byte ) == int :
self . _calldata . append ( BitVecVal ( calldata_byte , 8 ) )
self . _calldata . append ( BitVecVal ( calldata_byte , 8 ) )
else :
else :
self . _calldata . append ( calldata_byte )
self . _calldata . append ( calldata_byte )
constraints . append ( self . calldatasize == len ( self . starting_calldata ) )
else :
x = BitVec ( " x " , 256 )
constraints . append (
ForAll ( x , Implies ( self [ x ] != 0 , UGT ( self . calldatasize , x ) ) )
)
return constraints
def concretized ( self , model ) :
def concretized ( self , model ) :
result = [ ]
result = [ ]
for i in range (
for i in range (
get_concrete_int ( model . eval ( self . calldatasize , model_completion = True ) )
get_concrete_int ( model . eval ( self . calldatasize , model_completion = True ) )
) :
) :
result . append ( get_concrete_int ( model . eval ( self [ i ] , model_completion = True ) ) )
result . append (
get_concrete_int ( model . eval ( self . _calldata [ i ] , model_completion = True ) )
)
return result
return result
@ -108,15 +96,24 @@ class Calldata:
current_index = simplify ( current_index + step )
current_index = simplify ( current_index + step )
except Z3Exception :
except Z3Exception :
raise IndexError ( " Invalid Calldata Slice " )
raise IndexError ( " Invalid Calldata Slice " )
return simplify ( Concat ( dataparts ) )
values , constraints = zip ( * dataparts )
result_constraints = [ ]
for c in constraints :
result_constraints . extend ( c )
return simplify ( Concat ( values ) ) , result_constraints
if self . concrete :
if self . concrete :
try :
try :
return self . _calldata [ get_concrete_int ( item ) ]
return self . _calldata [ get_concrete_int ( item ) ] , ( )
except IndexError :
except IndexError :
return BitVecVal ( 0 , 8 )
return BitVecVal ( 0 , 8 ) , ( )
else :
else :
return self . _calldata [ item ]
constraints = [
Implies ( self . _calldata [ item ] != 0 , UGT ( self . calldatasize , item ) )
]
return self . _calldata [ item ] , constraints
class Storage :
class Storage :