(self, func, all_funcs_completed=False)
return False
Determine if a function returns or not.

        A function does not return if
        a) it is a SimProcedure that has NO_RET being True,
        or
        b) it is completely recovered (i.e. every block of this function has been recovered, and no future block will
           be added to it), and it does not have a ret or any equivalent instruction.

        A function returns if any of its block contains a ret instruction or any equivalence.

        :param Function func:   The function to work on.
        :param bool all_funcs_completed:    Whether we treat all functions as completed functions or not.
        :return:                True if the function returns, False if the function does not return, or None if it is
                                not yet determinable with the information available at the moment.
        :rtype:                 bool or None
Determine if a function returns or not.
Determine if a function returns or not .
def _determine_function_returning(self, func, all_funcs_completed=False):
        """
        Determine if a function returns or not.

        A function does not return if
        a) it is a SimProcedure that has NO_RET being True,
        or
        b) it is completely recovered (i.e. every block of this function has been recovered, and no future block will
           be added to it), and it does not have a ret or any equivalent instruction.

        A function returns if any of its block contains a ret instruction or any equivalence.

        :param Function func:   The function to work on.
        :param bool all_funcs_completed:    Whether we treat all functions as completed functions or not.
        :return:                True if the function returns, False if the function does not return, or None if it is
                                not yet determinable with the information available at the moment.
        :rtype:                 bool or None
        """

        # If there is at least one return site, then this function is definitely returning
        if func.has_return:
            return True

        # Let's first see if it's a known SimProcedure that does not return
        if self.project.is_hooked(func.addr):
            procedure = self.project.hooked_by(func.addr)
        else:
            try:
                procedure = self.project.simos.syscall_from_addr(func.addr, allow_unsupported=False)
            except AngrUnsupportedSyscallError:
                procedure = None

        if procedure is not None and hasattr(procedure, 'NO_RET'):
            return not procedure.NO_RET

        # did we finish analyzing this function?
        if not all_funcs_completed and func.addr not in self._completed_functions:
            return None

        if not func.block_addrs_set:
            # there is no block inside this function
            # it might happen if the function has been incorrectly identified as part of another function
            # the error will be corrected during post-processing. In fact at this moment we cannot say anything
            # about whether this function returns or not. We always assume it returns.
            return True

        bail_out = False

        # if this function has jump-out sites or ret-out sites, it returns as long as any of the target function
        # returns
        for goout_site, type_ in [(site, 'jumpout') for site in func.jumpout_sites] + \
                                 [(site, 'retout') for site in func.retout_sites]:

            # determine where it jumps/returns to
            goout_site_successors = goout_site.successors()
            if not goout_site_successors:
                # not sure where it jumps to. bail out
                bail_out = True
                continue

            # for ret-out sites, determine what function it calls
            if type_ == 'retout':
                # see whether the function being called returns or not
                func_successors = [succ for succ in goout_site_successors if isinstance(succ, Function)]
                if func_successors and all(func_successor.returning in (None, False)
                                           for func_successor in func_successors):
                    # the returning of all possible function calls are undetermined, or they do not return
                    # ignore this site
                    continue

            if type_ == 'retout':
                goout_target = next((succ for succ in goout_site_successors if not isinstance(succ, Function)), None)
            else:
                goout_target = next((succ for succ in goout_site_successors), None)
            if goout_target is None:
                # there is no jumpout site, which is weird, but what can we do...
                continue
            if not self.kb.functions.contains_addr(goout_target.addr):
                # wait it does not jump to a function?
                bail_out = True
                continue

            target_func = self.kb.functions[goout_target.addr]
            if target_func.returning is True:
                return True
            elif target_func.returning is None:
                # the returning status of at least one of the target functions is not decided yet.
                bail_out = True

        if bail_out:
            # We cannot determine at this point. bail out
            return None

        # well this function does not return then
        return False
def _determine_function_returning ( self , func , all_funcs_completed = False ) : # If there is at least one return site, then this function is definitely returning if func . has_return : return True # Let's first see if it's a known SimProcedure that does not return if self . project . is_hooked ( func . addr ) : procedure = self . project . hooked_by ( func . addr ) else : try : procedure = self . project . simos . syscall_from_addr ( func . addr , allow_unsupported = False ) except AngrUnsupportedSyscallError : procedure = None if procedure is not None and hasattr ( procedure , 'NO_RET' ) : return not procedure . NO_RET # did we finish analyzing this function? if not all_funcs_completed and func . addr not in self . _completed_functions : return None if not func . block_addrs_set : # there is no block inside this function # it might happen if the function has been incorrectly identified as part of another function # the error will be corrected during post-processing. In fact at this moment we cannot say anything # about whether this function returns or not. We always assume it returns. return True bail_out = False # if this function has jump-out sites or ret-out sites, it returns as long as any of the target function # returns for goout_site , type_ in [ ( site , 'jumpout' ) for site in func . jumpout_sites ] + [ ( site , 'retout' ) for site in func . retout_sites ] : # determine where it jumps/returns to goout_site_successors = goout_site . successors ( ) if not goout_site_successors : # not sure where it jumps to. bail out bail_out = True continue # for ret-out sites, determine what function it calls if type_ == 'retout' : # see whether the function being called returns or not func_successors = [ succ for succ in goout_site_successors if isinstance ( succ , Function ) ] if func_successors and all ( func_successor . returning in ( None , False ) for func_successor in func_successors ) : # the returning of all possible function calls are undetermined, or they do not return # ignore this site continue if type_ == 'retout' : goout_target = next ( ( succ for succ in goout_site_successors if not isinstance ( succ , Function ) ) , None ) else : goout_target = next ( ( succ for succ in goout_site_successors ) , None ) if goout_target is None : # there is no jumpout site, which is weird, but what can we do... continue if not self . kb . functions . contains_addr ( goout_target . addr ) : # wait it does not jump to a function? bail_out = True continue target_func = self . kb . functions [ goout_target . addr ] if target_func . returning is True : return True elif target_func . returning is None : # the returning status of at least one of the target functions is not decided yet. bail_out = True if bail_out : # We cannot determine at this point. bail out return None # well this function does not return then return False