Example #1
0
def pre_analyze(params):

    action, context, analyzer_config_map, skip_handler, \
        ctu_data, statistics_data = params

    analyzer_environment = analyzer_env.get_check_env(
        context.path_env_extra, context.ld_lib_path_extra)

    progress_checked_num.value += 1

    for source in action.sources:
        if skip_handler and skip_handler.should_skip(source):
            continue
        if action.analyzer_type != analyzer_types.CLANG_SA:
            continue

        _, source_filename = os.path.split(source)

        source = util.escape_source_path(source)

        LOG.info("[%d/%d] %s" % (progress_checked_num.value,
                                 progress_actions.value, source_filename))

        config = analyzer_config_map.get(analyzer_types.CLANG_SA)

        try:
            if ctu_data:
                LOG.debug("running CTU pre analysis")
                ctu_temp_fnmap_folder = ctu_data.get('ctu_temp_fnmap_folder')

                triple_arch = \
                    ctu_triple_arch.get_triple_arch(action, source,
                                                    config,
                                                    analyzer_environment)
                if not config.ctu_in_memory:
                    ctu_manager.generate_ast(triple_arch, action, source,
                                             config, analyzer_environment)
                ctu_manager.map_functions(triple_arch, action, source, config,
                                          analyzer_environment,
                                          context.ctu_func_map_cmd,
                                          ctu_temp_fnmap_folder)

        except Exception as ex:
            LOG.debug_analyzer(str(ex))
            traceback.print_exc(file=sys.stdout)
            raise

        try:
            if statistics_data:
                LOG.debug("running statistics pre analysis")
                collect_statistics(action, source, config,
                                   analyzer_environment, statistics_data)

        except Exception as ex:
            LOG.debug_analyzer(str(ex))
            traceback.print_exc(file=sys.stdout)
            raise
def check(check_data):
    """
    Invoke clang with an action which called by processes.
    Different analyzer object belongs to for each build action.

    skiplist handler is None if no skip file was configured.
    """

    actions_map, action, context, analyzer_config_map, \
        output_dir, skip_handler, quiet_output_on_stdout, \
        capture_analysis_output, analysis_timeout, \
        analyzer_environment, ctu_reanalyze_on_failure, \
        output_dirs, statistics_data = check_data

    skipped = False
    reanalyzed = False

    failed_dir = output_dirs["failed"]
    success_dir = output_dirs["success"]

    try:
        # If one analysis fails the check fails.
        return_codes = 0
        skipped = False

        result_file = ''
        for source in action.sources:

            # If there is no skiplist handler there was no skip list file
            # in the command line.
            # C++ file skipping is handled here.
            source_file_name = os.path.basename(source)

            if skip_handler and skip_handler.should_skip(source):
                LOG.debug_analyzer(source_file_name + ' is skipped')
                skipped = True
                continue

            source = util.escape_source_path(source)

            source_analyzer, analyzer_cmd, rh, reanalyzed = \
                prepare_check(source, action, analyzer_config_map,
                              output_dir, context.severity_map,
                              skip_handler, statistics_data)

            # The analyzer invocation calls __create_timeout as a callback
            # when the analyzer starts. This callback creates the timeout
            # watcher over the analyzer process, which in turn returns a
            # function, that can later be used to check if the analyzer quit
            # because we killed it due to a timeout.
            #
            # We need to capture the "function pointer" returned by
            # setup_process_timeout as reference, so that we may call it
            # later. To work around scoping issues, we use a list here so the
            # "function pointer" is captured by reference.
            timeout_cleanup = [lambda: False]

            if analysis_timeout and analysis_timeout > 0:
                def __create_timeout(analyzer_process):
                    """
                    Once the analyzer process is started, this method is
                    called. Set up a timeout for the analysis.
                    """
                    timeout_cleanup[0] = util.setup_process_timeout(
                        analyzer_process, analysis_timeout)
            else:
                def __create_timeout(analyzer_process):
                    # If no timeout is given by the client, this callback
                    # shouldn't do anything.
                    pass

            # Fills up the result handler with the analyzer information.
            source_analyzer.analyze(analyzer_cmd, rh, analyzer_environment,
                                    __create_timeout)

            # If execution reaches this line, the analyzer process has quit.
            if timeout_cleanup[0]():
                LOG.warning("Analyzer ran too long, exceeding time limit "
                            "of {0} seconds.".format(analysis_timeout))
                LOG.warning("Considering this analysis as failed...")
                rh.analyzer_returncode = -1
                rh.analyzer_stderr = (">>> CodeChecker: Analysis timed out "
                                      "after {0} seconds. <<<\n{1}") \
                    .format(analysis_timeout, rh.analyzer_stderr)

            # If source file contains escaped spaces ("\ " tokens), then
            # clangSA writes the plist file with removing this escape
            # sequence, whereas clang-tidy does not. We rewrite the file
            # names to contain no escape sequences for every analyzer.
            result_file = rh.analyzer_result_file.replace(r'\ ', ' ')
            result_base = os.path.basename(result_file)

            ctu_active = is_ctu_active(source_analyzer)

            ctu_suffix = 'CTU'
            zip_suffix = ctu_suffix if ctu_active else ''

            zip_file = result_base + zip_suffix + '.zip'
            zip_file = os.path.join(failed_dir, zip_file)

            ctu_zip_file = result_base + ctu_suffix + '.zip'
            ctu_zip_file = os.path.join(failed_dir, ctu_zip_file)

            return_codes = rh.analyzer_returncode
            if rh.analyzer_returncode == 0:

                # Remove the previously generated error file.
                if os.path.exists(zip_file):
                    os.remove(zip_file)

                # Remove the previously generated CTU error file.
                if os.path.exists(ctu_zip_file):
                    os.remove(ctu_zip_file)

                handle_success(rh, result_file, result_base,
                               skip_handler, capture_analysis_output,
                               success_dir)
                LOG.info("[%d/%d] %s analyzed %s successfully." %
                         (progress_checked_num.value, progress_actions.value,
                          action.analyzer_type, source_file_name))

                if skip_handler:
                    # We need to check the plist content because skipping
                    # reports in headers can be done only this way.
                    plist_parser.skip_report_from_plist(result_file,
                                                        skip_handler)

            else:
                LOG.error("Analyzing '" + source_file_name + "' with " +
                          action.analyzer_type +
                          " CTU" if ctu_active else " " + "failed.")

                if not quiet_output_on_stdout:
                    LOG.error('\n' + rh.analyzer_stdout)
                    LOG.error('\n' + rh.analyzer_stderr)

                handle_failure(source_analyzer, rh, action, zip_file,
                               result_base, actions_map)

                if ctu_active and ctu_reanalyze_on_failure:
                    LOG.error("Try to reanalyze without CTU")
                    # Try to reanalyze with CTU disabled.
                    source_analyzer, analyzer_cmd, rh, reanalyzed = \
                        prepare_check(source, action,
                                      analyzer_config_map,
                                      output_dir,
                                      context.severity_map,
                                      skip_handler,
                                      statistics_data,
                                      True)

                    # Fills up the result handler with
                    # the analyzer information.
                    source_analyzer.analyze(analyzer_cmd,
                                            rh,
                                            analyzer_environment)

                    return_codes = rh.analyzer_returncode
                    if rh.analyzer_returncode == 0:
                        handle_success(rh, result_file, result_base,
                                       skip_handler, capture_analysis_output,
                                       success_dir, zipfile)

                        msg = "[{0}/{1}] {2} analyzed {3} without" \
                            " CTU successfully.".format(
                                progress_checked_num.value,
                                progress_actions.value,
                                action.analyzer_type,
                                source_file_name)

                        LOG.info(msg)
                    else:
                        LOG.error("Analyzing '" + source_file_name +
                                  "' with " + action.analyzer_type +
                                  " without CTU failed.")

                        zip_file = result_base + '.zip'
                        zip_file = os.path.join(failed_dir, zip_file)
                        handle_failure(source_analyzer, rh, action,
                                       zip_file, result_base, actions_map)

            if not quiet_output_on_stdout:
                if rh.analyzer_returncode:
                    LOG.error('\n' + rh.analyzer_stdout)
                    LOG.error('\n' + rh.analyzer_stderr)
                else:
                    LOG.debug_analyzer('\n' + rh.analyzer_stdout)
                    LOG.debug_analyzer('\n' + rh.analyzer_stderr)

        progress_checked_num.value += 1

        return return_codes, skipped, reanalyzed, action.analyzer_type, \
            result_file, list(action.sources)

    except Exception as e:
        LOG.debug_analyzer(str(e))
        traceback.print_exc(file=sys.stdout)
        return 1, skipped, reanalyzed, action.analyzer_type, None, \
            list(action.sources)