Exemple #1
0
 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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #5
0
    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)
Exemple #6
0
 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
Exemple #7
0
    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'