(self, node, new_size, remove_function=True)
Shrink the size of a node in CFG.

        :param CFGNode node: The CFGNode to shrink
        :param int new_size: The new size of the basic block
        :param bool remove_function: If there is a function starting at `node`, should we remove that function or not.
        :return: None
Shrink the size of a node in CFG.
Shrink the size of a node in CFG .
def _shrink_node(self, node, new_size, remove_function=True):
        """
        Shrink the size of a node in CFG.

        :param CFGNode node: The CFGNode to shrink
        :param int new_size: The new size of the basic block
        :param bool remove_function: If there is a function starting at `node`, should we remove that function or not.
        :return: None
        """

        # Generate the new node
        new_node = CFGNode(node.addr, new_size, self.model,
                           function_address=None if remove_function else node.function_address,
                           instruction_addrs=[i for i in node.instruction_addrs
                                                     if node.addr <= i < node.addr + new_size
                                                   ],
                           thumb=node.thumb,
                           byte_string=None if node.byte_string is None else node.byte_string[:new_size],
                           block_id=node.addr,
                           )

        old_in_edges = self.graph.in_edges(node, data=True)

        for src, _, data in old_in_edges:
            self.graph.add_edge(src, new_node, **data)

        successor_node_addr = node.addr + new_size
        if successor_node_addr in self._nodes:
            successor = self._nodes[successor_node_addr]
        else:
            successor_size = node.size - new_size
            successor = CFGNode(successor_node_addr, successor_size, self.model,
                                function_address=successor_node_addr if remove_function else node.function_address,
                                instruction_addrs=[i for i in node.instruction_addrs if i >= node.addr + new_size],
                                thumb=node.thumb,
                                byte_string=None if node.byte_string is None else node.byte_string[new_size:]
                                )
        self.graph.add_edge(new_node, successor, jumpkind='Ijk_Boring')

        # if the node B already has resolved targets, we will skip all unresolvable successors when adding old out edges
        # from node A to node B.
        # this matters in cases where node B is resolved as a special indirect jump entry (like a PLT stub), but (node
        # A + node B) wasn't properly resolved.
        unresolvable_target_addrs = (self._unresolvable_jump_target_addr, self._unresolvable_call_target_addr)

        has_resolved_targets = any([ node_.addr not in unresolvable_target_addrs
                                     for node_ in self.graph.successors(successor) ]
                                   )

        old_out_edges = self.graph.out_edges(node, data=True)
        for _, dst, data in old_out_edges:
            if (has_resolved_targets and dst.addr not in unresolvable_target_addrs) or \
                    not has_resolved_targets:
                self.graph.add_edge(successor, dst, **data)

        # remove the old node from indices
        self._model.remove_node(node.addr, node)

        # remove the old node form the graph
        self.graph.remove_node(node)

        # add the new node to indices
        self._model.add_node(new_node.addr, new_node)

        # the function starting at this point is probably totally incorrect
        # hopefull future call to `make_functions()` will correct everything
        if node.addr in self.kb.functions:
            del self.kb.functions[node.addr]

            if not remove_function:
                # add functions back
                self._function_add_node(node, node.addr)
                successor_node = self.model.get_any_node(successor_node_addr)
                if successor_node and successor_node.function_address == node.addr:
                    # if there is absolutely no predecessors to successor_node, we'd like to add it as a new function
                    # so that it will not be left behind
                    if not list(self.graph.predecessors(successor_node)):
                        self._function_add_node(successor_node, successor_node_addr)
def _shrink_node ( self , node , new_size , remove_function = True ) : # Generate the new node new_node = CFGNode ( node . addr , new_size , self . model , function_address = None if remove_function else node . function_address , instruction_addrs = [ i for i in node . instruction_addrs if node . addr <= i < node . addr + new_size ] , thumb = node . thumb , byte_string = None if node . byte_string is None else node . byte_string [ : new_size ] , block_id = node . addr , ) old_in_edges = self . graph . in_edges ( node , data = True ) for src , _ , data in old_in_edges : self . graph . add_edge ( src , new_node , * * data ) successor_node_addr = node . addr + new_size if successor_node_addr in self . _nodes : successor = self . _nodes [ successor_node_addr ] else : successor_size = node . size - new_size successor = CFGNode ( successor_node_addr , successor_size , self . model , function_address = successor_node_addr if remove_function else node . function_address , instruction_addrs = [ i for i in node . instruction_addrs if i >= node . addr + new_size ] , thumb = node . thumb , byte_string = None if node . byte_string is None else node . byte_string [ new_size : ] ) self . graph . add_edge ( new_node , successor , jumpkind = 'Ijk_Boring' ) # if the node B already has resolved targets, we will skip all unresolvable successors when adding old out edges # from node A to node B. # this matters in cases where node B is resolved as a special indirect jump entry (like a PLT stub), but (node # A + node B) wasn't properly resolved. unresolvable_target_addrs = ( self . _unresolvable_jump_target_addr , self . _unresolvable_call_target_addr ) has_resolved_targets = any ( [ node_ . addr not in unresolvable_target_addrs for node_ in self . graph . successors ( successor ) ] ) old_out_edges = self . graph . out_edges ( node , data = True ) for _ , dst , data in old_out_edges : if ( has_resolved_targets and dst . addr not in unresolvable_target_addrs ) or not has_resolved_targets : self . graph . add_edge ( successor , dst , * * data ) # remove the old node from indices self . _model . remove_node ( node . addr , node ) # remove the old node form the graph self . graph . remove_node ( node ) # add the new node to indices self . _model . add_node ( new_node . addr , new_node ) # the function starting at this point is probably totally incorrect # hopefull future call to `make_functions()` will correct everything if node . addr in self . kb . functions : del self . kb . functions [ node . addr ] if not remove_function : # add functions back self . _function_add_node ( node , node . addr ) successor_node = self . model . get_any_node ( successor_node_addr ) if successor_node and successor_node . function_address == node . addr : # if there is absolutely no predecessors to successor_node, we'd like to add it as a new function # so that it will not be left behind if not list ( self . graph . predecessors ( successor_node ) ) : self . _function_add_node ( successor_node , successor_node_addr )