def __init__(self, vertices): self.vertices = vertices # edges are found and added as a parameter (type list) edges = [] for i in range(len(vertices) - 1): e = Edge(vertices[i], vertices[i + 1]) edges.append(e) edges.append(Edge(vertices[-1], vertices[0])) self.edges = edges
def add_edge(self, id1: int, id2: int, weight: float): ans = False if id1 != id2 and self.__Nodes.get( id1) is not None and self.__Nodes.get( id2) is not None and weight >= 0: if self.__Edges.get(id1).get(id2) is None: e = Edge(id1, id2, weight) self.__Edges.get(id1).update({id2: e}) self.__allInEdges.get(id2).update({id1: e}) self.__mc += 1 self.__edgeSize += 1 ans = True elif self.__Edges.get(id1).get( id2) is not None and self.__Edges.get(id1).get( id2).getWeight() != weight: self.__Edges.get(id1).get(id2).setWeight(weight) self.__mc += 1 ans = True return ans
def kruskalMST(self): self.MST_weight = 0 sumOfWeights = 0 self.edges.sort(key=lambda x: x.w, reverse=False) ds = DisjointSet(self.numVertices) for e in self.edges: u = e.u v = e.v set_of_u = ds.Find(u) set_of_v = ds.Find(v) if set_of_u != set_of_v: w = e.w self.MST.append(Edge(u, v, w)) sumOfWeights += w ds.Union(set_of_u, set_of_v) for mst_edge in self.MST: for original_edge in self.original_edges: if original_edge.u == mst_edge.u and original_edge.v == mst_edge.v: self.MST_weight = self.MST_weight + original_edge.w # mst_edge.w = original_edge.w break return sumOfWeights
containsE = False for edge in polygon.edges: if e.start == edge.start and e.end == edge.end: containsE = True # proceed only if edge is in polygon, point is in interior, and it is a # valid addition to the polygon if containsE and point in points and e.valid(polygon, point): # get index of the edge for edge in polygon.edges: if e.start == edge.start and e.end == edge.end: i = polygon.edges.index(edge) # insert new edges and point into the polygon, # remove old edge from polygon and remove point from interior polygon.vertices.insert(i + 1, point) polygon.edges[i] = Edge(e.start, point) polygon.edges.insert(i + 1, Edge(point, e.end)) points.remove(point) # update MinPQ by adding distances between two new edges # and every point in interior e1 = Edge(e.start, point) e2 = Edge(point, e.end) for point in points: curr_dist_e1 = pnt2line(point, e1.start, e1.end) curr_dist_e2 = pnt2line(point, e2.start, e2.end) heapq.heappush(distances, curr_dist_e1) heapq.heappush(distances, curr_dist_e2) distancesDict[curr_dist_e1] = (e1, point) distancesDict[curr_dist_e2] = (e2, point) # print results
def symbolic_execution(self, tag: int, path: Path, state: State) -> None: from src.Result import Result # logging.debug('TAG: %s' % tag) # if settings.DETECT_LOOP: # return node = self.cfg.get_node(tag) if not node: return node.visit() node.init_state = deepcopy(state) gas = 0 if node.count % 10 == 0: logging.debug('%s visit %s times' % (tag, node.count)) if ENABLE_MAX_NODE_VISITED_TIMES and node.count > MAX_NODE_VISITED_TIMES: return for opcode in node.opcodes: # NOTE: state simulation result = state.simulate(opcode, self.variables) # if tag in [1133]: # logging.debug('%s: %s' % (opcode.pc, opcode.name)) # logging.debug('Stack: %s\n' % self.to_string(state.stack)) # logging.debug('MEM: %s' % self.to_string(state.memory)) # logging.debug('STO: %s\n' % self.to_string(state.storage)) path.add_path_constraints(result.path_constraints) gas += result.gas gas = simplify(gas) if is_expr(gas) else gas path.add_gas(result.gas) path.add_memory_gas(result.memory_gas) if opcode.name == 'JUMP': # NOTE: set gas to node node.set_gas(gas) node.set_state(deepcopy(state)) # NOTE: add tag to the path list path.add_node(deepcopy(node)) # NOTE: if edge is not in edges -> add edge into edges self.__add_edge(Edge(node.tag, result.jump_tag, 'red')) return self.symbolic_execution(result.jump_tag, path, state) elif opcode.name == 'JUMPI': tmp_cond = simplify(result.jump_condition) if is_expr( result.jump_condition) else result.jump_condition result.jump_condition = int(tmp_cond.as_long()) if isinstance( tmp_cond, BitVecNumRef) else result.jump_condition node.set_path_constraint(result.jump_condition) # NOTE: Loop detection detect_loop = False if LOOP_DETECTION: if path.count_specific_node_num(node.tag) > 0 and is_expr( result.jump_condition): jump_condition, jump_condition_n1 = path.handle_loop( node, opcode.pc, self.variables, self.cfg) if jump_condition is not None: detect_loop = True result.jump_condition = jump_condition if str( jump_condition ) != 'same' else result.jump_condition elif path.count_specific_node_num( node.tag) >= MAX_LOOP_ITERATIONS - 1: # LOG ERROR err_result = Result() err_message = 'Loop Error:[%s] %s' % ( tag, result.jump_condition) err_result.log_error(settings.ADDRESS, err_message) logging.error(err_message) return else: path_cond = simplify(node.path_constraint) if is_expr( node.path_constraint) else node.path_constraint if path.count_specific_node_num( node.tag) >= MAX_LOOP_ITERATIONS and is_expr( path_cond): for node in self.cfg.nodes: if node.tag == tag: node.loop_condition.append( path.find_loop_condition(node)) return # NOTE: if edge is not in edges -> add edge into edges self.__add_edge(Edge(node.tag, result.jump_tag, 'red')) self.__add_edge(Edge(node.tag, opcode.get_next_pc(), 'red')) edge_true = self.cfg.get_edge(node.tag, result.jump_tag) edge_false = self.cfg.get_edge(node.tag, opcode.get_next_pc()) if detect_loop: edge_true.set_path_constraint( self.to_string(simplify(result.jump_condition == 1))) edge_false.set_path_constraint( self.to_string(simplify(result.jump_condition == 0))) if path.contain_node(result.jump_tag): jump_condition_n1 = 0 if jump_condition_n1 is None else jump_condition_n1 path.add_path_constraints([ result.jump_condition == 1, jump_condition_n1 == 1 ]) return self.symbolic_execution(opcode.get_next_pc(), deepcopy(path), deepcopy(state)) elif path.contain_node(opcode.get_next_pc()): jump_condition_n1 = 1 if jump_condition_n1 is None else jump_condition_n1 path.add_path_constraints([ result.jump_condition == 0, jump_condition_n1 == 0 ]) return self.symbolic_execution(result.jump_tag, deepcopy(path), deepcopy(state)) else: # LOG ERROR err_result = Result() err_message = 'Loop Error:[%s] Both JUMPDEST tags have been executed' % tag err_result.log_error(settings.ADDRESS, err_message) raise ValueError(err_message) else: # NOTE: set gas to node node.set_gas(gas) node.set_state(deepcopy(state)) # NOTE: add tag to the path list path.add_node(deepcopy(node)) # NOTE: Jump to two path if isinstance(result.jump_condition, int) and result.jump_condition == 1: edge_true.set_path_constraint('True') edge_false.set_path_constraint('False') return self.symbolic_execution(result.jump_tag, deepcopy(path), deepcopy(state)) elif isinstance(result.jump_condition, int) and result.jump_condition == 0: edge_true.set_path_constraint('False') edge_false.set_path_constraint('True') return self.symbolic_execution(opcode.get_next_pc(), deepcopy(path), deepcopy(state)) elif isinstance(result.jump_condition, int): return else: edge_true.set_path_constraint( self.to_string( simplify(result.jump_condition == 1))) edge_false.set_path_constraint( self.to_string( simplify(result.jump_condition == 0))) true_path, false_path = deepcopy(path), deepcopy(path) true_state, false_state = deepcopy(state), deepcopy( state) true_path.add_path_constraints( [result.jump_condition == 1]) false_path.add_path_constraints( [result.jump_condition == 0]) self.symbolic_execution(result.jump_tag, true_path, true_state) self.symbolic_execution(opcode.get_next_pc(), false_path, false_state) return elif opcode.name in [ 'STOP', 'RETURN', 'REVERT', 'INVALID', 'SELFDESTRUCT' ]: # NOTE: set gas to node node.set_gas(gas) node.set_state(deepcopy(state)) # NOTE: add tag to the path list path.add_node(deepcopy(node)) # NOTE: simplify gas formula path.gas = simplify(path.gas) if is_expr(path.gas) else int( path.gas) path.gas = int(path.gas.as_long()) if isinstance( path.gas, BitVecNumRef) else path.gas path.gas = int(path.gas) if isinstance(path.gas, float) else path.gas # NOTE: solve gas satisfiability & set gas type if path.solve(): if isinstance(path.gas, int): path.set_gas_type('constant') elif 'loop' in str(path.gas) and path.solve_unbound(): settings.DETECT_LOOP = True path.set_gas_type('unbound') logging.debug('Detect loop') else: path.set_gas_type('bound') self.paths.append(path) self.count_path += 1 logging.debug('Finish one path...[%s]' % self.count_path) return """ NOTE: the end of the node is not in block ins -> jump to next node """ # NOTE: set gas to node node.set_gas(gas) # NOTE: add tag to the path list path.add_node(deepcopy(node)) # NOTE: if edge is not in edges -> add edge into edges self.__add_edge(Edge(node.tag, opcode.get_next_pc(), 'red')) return self.symbolic_execution(opcode.get_next_pc(), path, state)
def addEdge(self, u, v, weight=1): self.edges.append(Edge(u, v, weight)) self.original_edges.append(Edge(u, v, weight)) self.adjMatrix[u][v] = 1 self.adjMatrix[v][u] = 1
def build_cfg(self, opcode_data: str) -> None: logging.info('Constructing CFG...') start_list = list() opcode_list = opcode_data.split('\n') for i in range(len(opcode_list)): code_set = opcode_list[i].rstrip().split(' ') pc = int(code_set[0].replace(':', '')) s = code_set[1:] opcode = Opcode(pc, s[0], None) if len(s) == 1 else Opcode( pc, s[0], s[1]) self.opcodes.append(opcode) push_value = '' pre_opcode = None start_idx = 0 start_pc = 0 end_start_tag = 0 add_start = True function_start = False function_hashes = '' for index, opcode in enumerate(self.opcodes): if opcode.pc == 9 and opcode.name.startswith('PUSH'): end_start_tag = int(str(opcode.value), 16) start_list.append(int(str(opcode.value), 16)) if opcode.name == 'JUMPDEST' and start_idx != index: content = self.opcodes[start_idx:index] node = Node(start_pc, content) self.nodes.append(node) if pre_opcode.name not in [ 'JUMP', 'JUMPI', 'STOP', 'RETURN', 'REVERT', 'INVALID', 'SELFDESTRUCT' ]: edge = Edge(start_pc, opcode.pc) self.edges.append(edge) start_idx = index start_pc = opcode.pc elif opcode.name.startswith('PUSH'): if add_start: if opcode.name == 'PUSH4' and opcode.value != '0xFFFFFFFF': function_hashes = opcode.value function_start = True if function_start and opcode.name == 'PUSH2': self.function_map[function_hashes] = int( str(opcode.value), 16) start_list.append(int(str(opcode.value), 16)) function_start = False function_hashes = '' push_value = opcode.value elif opcode.name == 'JUMP': content = self.opcodes[start_idx:index + 1] node = Node(start_pc, content) self.nodes.append(node) if pre_opcode.name.startswith('PUSH'): edge = Edge(start_pc, int(pre_opcode.value, 16)) self.edges.append(edge) start_idx = index + 1 start_pc = opcode.pc + 1 elif opcode.name == 'JUMPI': content = self.opcodes[start_idx:index + 1] node = Node(start_pc, content) node.set_color('purple') self.nodes.append(node) if pre_opcode.name.startswith('PUSH'): edge = Edge(start_pc, int(pre_opcode.value, 16)) self.edges.append(edge) edge = Edge(start_pc, opcode.pc + 1) self.edges.append(edge) start_idx = index + 1 start_pc = opcode.pc + 1 if opcode.pc == end_start_tag - 1: add_start = False elif opcode.name in [ 'STOP', 'RETURN', 'REVERT', 'INVALID', 'SELFDESTRUCT' ]: content = self.opcodes[start_idx:index + 1] node = Node(start_pc, content) if opcode.name == 'RETURN': node.set_color('green') elif opcode.name == 'STOP': node.set_color('blue') else: node.set_color('red') self.nodes.append(node) start_idx = index + 1 start_pc = opcode.pc + 1 pre_opcode = opcode for node in self.nodes: if node.tag in start_list: node.color = 'yellow'