Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_concat_extract_assignment():
inp1 = symbol_factory.BitVecSym("input1", 256)
inp2 = symbol_factory.BitVecSym("input2", 256)
output1 = symbol_factory.BitVecFuncSym(
"Keccak[input]", size=256, func_name="keccak256", input_=Concat(inp1, inp2)
)
output = Concat(output1, symbol_factory.BitVecVal(0, 256))
cond = And(output1 == inp2, inp1 == inp2)
Extract(511, 256, output).potential_input_cond = cond
assert Extract(511, 256, output).potential_input_cond == cond
def _merge_constraints(
constraints1: Constraints, constraints2: Constraints
) -> Tuple[Constraints, Bool, Bool]:
dict1, dict2 = {}, {}
for constraint in constraints1:
dict1[constraint] = True
for constraint in constraints2:
dict2[constraint] = True
c1, c2 = symbol_factory.Bool(True), symbol_factory.Bool(True)
new_constraint1, new_constraint2 = (
symbol_factory.Bool(True),
symbol_factory.Bool(True),
)
same_constraints = Constraints()
for key in dict1:
if key not in dict2:
c1 = And(c1, key)
if Not(key) not in dict2:
new_constraint1 = And(new_constraint1, key)
else:
same_constraints.append(key)
for key in dict2:
if key not in dict1:
c2 = And(c2, key)
if Not(key) not in dict1:
func, inv = self.get_function(length)
try:
index = self.interval_hook_for_size[length]
except KeyError:
self.interval_hook_for_size[length] = self._index_counter
index = self._index_counter
self._index_counter -= INTERVAL_DIFFERENCE
lower_bound = index * PART
upper_bound = lower_bound + PART
cond = And(
inv(func(func_input)) == func_input,
ULE(symbol_factory.BitVecVal(lower_bound, 256), func(func_input)),
ULT(func(func_input), symbol_factory.BitVecVal(upper_bound, 256)),
URem(func(func_input), symbol_factory.BitVecVal(64, 256)) == 0,
)
return cond
:param active_account:
:param sender:
:param calldata:
:param gasprice:
:param callvalue:
:param origin:
:param code:
:param static: Makes the environment static.
"""
# Metadata
self.active_account = active_account
self.active_function_name = ""
self.address = active_account.address
self.block_number = symbol_factory.BitVecSym("block_number", 256)
# Ib
self.code = active_account.code if code is None else code
self.sender = sender
self.calldata = calldata
self.gasprice = gasprice
self.origin = origin
self.callvalue = callvalue
self.static = static
state.get_current_instruction()["address"],
add_constraints=annotation.add_constraints,
)
)
break
elif opcode == "BLOCKHASH":
param = state.mstate.stack[-1]
try:
constraint = [
ULT(param, state.environment.block_number),
ULT(
state.environment.block_number,
symbol_factory.BitVecVal(2 ** 255, 256),
),
]
# Why the second constraint? Because without it Z3 returns a solution where param overflows.
solver.get_model(state.mstate.constraints + constraint)
state.annotate(OldBlockNumberUsedAnnotation(constraint))
except UnsatError:
pass
else:
# we're in post hook
opcode = state.environment.code.instruction_list[state.mstate.pc - 1][
"opcode"
def get_issue(
self, global_state: GlobalState, detector: DetectionModule
) -> Optional[PotentialIssue]:
if not self.state_change_states:
return None
constraints = Constraints()
gas = self.call_state.mstate.stack[-1]
to = self.call_state.mstate.stack[-2]
constraints += [
UGT(gas, symbol_factory.BitVecVal(2300, 256)),
Or(
to > symbol_factory.BitVecVal(16, 256),
to == symbol_factory.BitVecVal(0, 256),
),
]
if self.user_defined_address:
constraints += [to == 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF]
try:
solver.get_transaction_sequence(
global_state, constraints + global_state.mstate.constraints
)
except UnsatError:
return None
severity = "Medium" if self.user_defined_address else "Low"
address = global_state.get_current_instruction()["address"]
logging.debug(
"[EXTERNAL_CALLS] Detected state changes at addresses: {}".format(address)
def __init__(self, tx_id: str) -> None:
"""Initializes the SymbolicCalldata object.
:param tx_id: Id of the transaction that the calldata is for.
"""
self._size = symbol_factory.BitVecSym(str(tx_id) + "_calldatasize", 256)
self._calldata = Array("{}_calldata".format(tx_id), 256, 8)
super().__init__(tx_id)
raise ValueError("dynamic_loader is None")
log.debug("Attempting to load dependency")
try:
code = dynamic_loader.dynld(callee_address)
except ValueError as error:
log.debug("Unable to execute dynamic loader because: %s", error)
raise error
if code is None:
log.debug("No code returned, not a contract account?")
raise ValueError("No code returned")
log.debug("Dependency loaded: " + callee_address)
callee_account = Account(
symbol_factory.BitVecVal(int(callee_address, 16), 256),
code,
callee_address,
dynamic_loader=dynamic_loader,
balances=global_state.world_state.balances,
)
global_state.accounts[int(callee_address, 16)] = callee_account
return callee_account
:param constraints: The constraints array which should contain any added constraints
:param minimize: The minimisation array which should contain any variables that should be minimised
:param max_size: The max size of the calldata array
:return: updated constraints, minimize
"""
for transaction in transaction_sequence:
# Set upper bound on calldata size
max_calldata_size = symbol_factory.BitVecVal(max_size, 256)
constraints.append(UGE(max_calldata_size, transaction.call_data.calldatasize))
# Minimize
minimize.append(transaction.call_data.calldatasize)
minimize.append(transaction.call_value)
constraints.append(
UGE(
symbol_factory.BitVecVal(1000000000000000000000, 256),
world_state.starting_balances[transaction.caller],
)
)
for account in world_state.accounts.values():
# Lazy way to prevent overflows and to ensure "reasonable" balances
# Each account starts with less than 100 ETH
constraints.append(
UGE(
symbol_factory.BitVecVal(100000000000000000000, 256),
world_state.starting_balances[account.address],
)
)
return constraints, tuple(minimize)