def _search_children(statespace, node, expression, taint_result=None, constraint=[], index=0, depth=0, max_depth=64): """ Checks the statespace for children states, with JUMPI or SSTORE instuctions, for dependency on expression :param statespace: The statespace to explore :param node: Current node to explore from :param expression: Expression to look for :param taint_result: Result of taint analysis :param index: Current state index node.states[index] == current_state :param depth: Current depth level :param max_depth: Max depth to explore :return: List of states that match the opcodes and are dependent on expression """ logging.debug("SEARCHING NODE for usage of an overflowed variable %d", node.uid) if taint_result is None: state = node.states[index] taint_stack = [False for _ in state.mstate.stack] taint_stack[-1] = True taint_result = TaintRunner.execute(statespace, node, state, initial_stack=taint_stack) results = [] if depth >= max_depth: return [] # Explore current node from index for j in range(index, len(node.states)): current_state = node.states[j] current_instruction = current_state.get_current_instruction() if current_instruction['opcode'] in ('JUMPI', 'SSTORE'): element = _check_usage(current_state, taint_result) if len(element) < 1: continue if _check_requires(element[0], node, statespace, constraint): continue results += element # Recursively search children children = \ [ statespace.nodes[edge.node_to] for edge in statespace.edges if edge.node_from == node.uid # and _try_constraints(statespace.nodes[edge.node_to].constraints, constraint) is not None ] for child in children: results += _search_children(statespace, child, expression, taint_result, depth=depth + 1, max_depth=max_depth) return results
def execute(statespace): """ Executes the analysis module""" #logging.debug("Executing module: TOKEN2") issues = [] taints = [] for state, node in _get_states_with_opcode(statespace, "CALLDATALOAD"): #state = node.states[index] taint_stack = [False for _ in state.mstate.stack] taint_stack[-1] = True taints.append(TaintRunner.execute(statespace, node, state, initial_stack=taint_stack)) for state, node in _get_tainted_sstores(statespace, taints): funtcion_we_are_in = node.contract_name + "." + node.function_name following_sstores = _get_sstore_along_the_line(statespace, node) if len(following_sstores) > 0: # logging.debug("SSTORE"*10) # logging.info("Found SSTORE %s following an SSTORE in (%s)"%(len(following_sstores), funtcion_we_are_in)) # logging.debug("%s: BEGIN Contraints of first SSTORE"%(funtcion_we_are_in)) #print("%s found following stores (%s)"%(funtcion_we_are_in, len(following_sstores))) r_n_constraints = list(map(_normalize_constraint, filter(_relevant_constraint, node.constraints))) # for c in r_n_constraints: # logging.info(c) matches = check_for_token_pattern(state, following_sstores, r_n_constraints, funtcion_we_are_in) if len(matches) > 0: issues.append(Issue(node.contract_name, node.function_name, None, "Found a transfer like function", "WUPI")) else: pass #logging.info("Found no matching sstores") # logging.debug("%s: END Contraints, those where the relevant constraints"%(funtcion_we_are_in)) # logging.debug("%s: Leading value =\n%s"%(funtcion_we_are_in, _get_value_sstore(state))) # logging.debug("%s: Following value =\n%s"%(funtcion_we_are_in, _get_value_sstore(following_sstores[0]))) # logging.debug("SSTORE"*10) else: pass #logging.info("%s: FOUND SSTORE (%s), but nothing followed"%(funtcion_we_are_in, _get_value_sstore(state))) return issues