Beispiel #1
0
    def __process_report_file(self, report_file_path: str, session: DBSession,
                              source_root: str, run_id: int,
                              file_path_to_id: Dict[str, int],
                              run_history_time: datetime,
                              skip_handler: skiplist_handler.SkipListHandler,
                              hash_map_reports: Dict[str, List[Any]]) -> bool:
        """
        Process and save reports from the given report file to the database.
        """
        try:
            files, reports = plist_parser.parse_plist_file(report_file_path)
        except Exception as ex:
            LOG.warning('Parsing the plist failed: %s', str(ex))
            return False

        if not reports:
            return True

        trimmed_files = {}
        file_ids = {}
        missing_ids_for_files = []

        for k, v in files.items():
            trimmed_files[k] = \
                util.trim_path_prefixes(v, self.__trim_path_prefixes)

        for file_name in trimmed_files.values():
            file_id = file_path_to_id.get(file_name, -1)
            if file_id == -1:
                missing_ids_for_files.append(file_name)
                continue

            file_ids[file_name] = file_id

        if missing_ids_for_files:
            LOG.warning("Failed to get file path id for '%s'!",
                        ' '.join(missing_ids_for_files))
            return False

        def set_review_status(report: ReportType):
            """
            Set review status for the given report if there is any source code
            comment.
            """
            checker_name = report.main['check_name']
            last_report_event = report.bug_path[-1]

            # The original file path is needed here not the trimmed
            # because the source files are extracted as the original
            # file path.
            file_name = files[last_report_event['location']['file']]

            source_file_name = os.path.realpath(
                os.path.join(source_root, file_name.strip("/")))

            # Check and store source code comments.
            if not os.path.isfile(source_file_name):
                return

            report_line = last_report_event['location']['line']
            source_file = os.path.basename(file_name)

            src_comment_data = parse_codechecker_review_comment(
                source_file_name, report_line, checker_name)

            if len(src_comment_data) == 1:
                status = src_comment_data[0]['status']
                rw_status = ttypes.ReviewStatus.FALSE_POSITIVE
                if status == 'confirmed':
                    rw_status = ttypes.ReviewStatus.CONFIRMED
                elif status == 'intentional':
                    rw_status = ttypes.ReviewStatus.INTENTIONAL

                self.__report_server._setReviewStatus(
                    session, report.report_hash, rw_status,
                    src_comment_data[0]['message'], run_history_time)
            elif len(src_comment_data) > 1:
                LOG.warning(
                    "Multiple source code comment can be found "
                    "for '%s' checker in '%s' at line %s. "
                    "This bug will not be suppressed!", checker_name,
                    source_file, report_line)

                self.__wrong_src_code_comments.append(
                    f"{source_file}|{report_line}|{checker_name}")

        root_dir_path = os.path.dirname(report_file_path)
        mip = self.__mips[root_dir_path]
        analysis_info = self.__analysis_info.get(root_dir_path)

        for report in reports:
            self.__all_report_checkers.add(report.check_name)

            if skip_handler.should_skip(report.file_path):
                continue

            report.trim_path_prefixes(self.__trim_path_prefixes)

            report_path_hash = get_report_path_hash(report)
            if report_path_hash in self.__already_added_report_hashes:
                LOG.debug('Not storing report. Already added: %s', report)
                continue

            LOG.debug("Storing report to the database...")

            bug_id = report.report_hash

            detection_status = 'new'
            detected_at = run_history_time

            if bug_id in hash_map_reports:
                old_report = hash_map_reports[bug_id][0]
                old_status = old_report.detection_status
                detection_status = 'reopened' \
                    if old_status == 'resolved' else 'unresolved'
                detected_at = old_report.detected_at

            analyzer_name = get_analyzer_name(report.check_name,
                                              mip.checker_to_analyzer,
                                              report.metadata)

            path_events = collect_paths_events(report, file_ids, trimmed_files)

            report_id = self.__add_report(session, run_id,
                                          file_ids[report.file_path],
                                          report.main, path_events,
                                          detection_status, detected_at,
                                          analysis_info, analyzer_name)

            self.__new_report_hashes.add(bug_id)
            self.__already_added_report_hashes.add(report_path_hash)

            set_review_status(report)

            LOG.debug("Storing report done. ID=%d", report_id)

        return True
    def __process_report_file(
        self,
        report_file_path: str,
        session: DBSession,
        source_root: str,
        run_id: int,
        file_path_to_id: Dict[str, int],
        run_history_time: datetime,
        skip_handler: skiplist_handler.SkipListHandler,
        hash_map_reports: Dict[str, List[Any]]
    ) -> bool:
        """
        Process and save reports from the given report file to the database.
        """
        reports = report_file.get_reports(report_file_path)

        if not reports:
            return True

        def set_review_status(report: Report):
            """
            Set review status for the given report if there is any source code
            comment.
            """
            checker_name = report.checker_name
            last_report_event = report.bug_path_events[-1]

            # The original file path is needed here, not the trimmed, because
            # the source files are extracted as the original file path.
            file_name = report.file.original_path

            source_file_name = os.path.realpath(
                os.path.join(source_root, file_name.strip("/")))

            # Check and store source code comments.
            if not os.path.isfile(source_file_name):
                return

            report_line = last_report_event.range.end_line
            source_file = os.path.basename(file_name)

            src_comment_data = parse_codechecker_review_comment(
                source_file_name, report_line, checker_name)

            if len(src_comment_data) == 1:
                status = src_comment_data[0].status
                rw_status = ttypes.ReviewStatus.FALSE_POSITIVE
                if status == 'confirmed':
                    rw_status = ttypes.ReviewStatus.CONFIRMED
                elif status == 'intentional':
                    rw_status = ttypes.ReviewStatus.INTENTIONAL

                self.__report_server._setReviewStatus(
                    session, report.report_hash, rw_status,
                    src_comment_data[0].message, run_history_time)
            elif len(src_comment_data) > 1:
                LOG.warning(
                    "Multiple source code comment can be found "
                    "for '%s' checker in '%s' at line %s. "
                    "This bug will not be suppressed!",
                    checker_name, source_file, report_line)

                self.__wrong_src_code_comments.append(
                    f"{source_file}|{report_line}|{checker_name}")

        def get_missing_file_ids(report: Report) -> List[str]:
            """ Returns file paths which database file id is missing. """
            missing_ids_for_files = []
            for file_path in report.trimmed_files:
                file_id = file_path_to_id.get(file_path, -1)
                if file_id == -1:
                    missing_ids_for_files.append(file_path)

            return missing_ids_for_files

        root_dir_path = os.path.dirname(report_file_path)
        mip = self.__mips[root_dir_path]
        analysis_info = self.__analysis_info.get(root_dir_path)

        for report in reports:
            report.trim_path_prefixes(self.__trim_path_prefixes)

            missing_ids_for_files = get_missing_file_ids(report)
            if missing_ids_for_files:
                LOG.warning("Failed to get database id for file path '%s'! "
                            "Skip adding report: %s:%d:%d [%s]",
                            ' '.join(missing_ids_for_files), report.file.path,
                            report.line, report.column, report.checker_name)
                continue

            self.__all_report_checkers.add(report.checker_name)

            if skip_handler.should_skip(report.file.original_path):
                continue

            report_path_hash = get_report_path_hash(report)
            if report_path_hash in self.__already_added_report_hashes:
                LOG.debug('Not storing report. Already added: %s', report)
                continue

            LOG.debug("Storing report to the database...")

            detection_status = 'new'
            detected_at = run_history_time

            if report.report_hash in hash_map_reports:
                old_report = hash_map_reports[report.report_hash][0]
                old_status = old_report.detection_status
                detection_status = 'reopened' \
                    if old_status == 'resolved' else 'unresolved'
                detected_at = old_report.detected_at

            analyzer_name = mip.checker_to_analyzer.get(
                report.checker_name, report.analyzer_name)

            report_id = self.__add_report(
                session, run_id, report, file_path_to_id,
                detection_status, detected_at, analysis_info, analyzer_name)

            self.__new_report_hashes.add(report.report_hash)
            self.__already_added_report_hashes.add(report_path_hash)

            set_review_status(report)

            LOG.debug("Storing report done. ID=%d", report_id)

        return True