From 23f9a04a6d7d1bd7ae837faebcb06dec240858a0 Mon Sep 17 00:00:00 2001 From: Nora Zinaeddin Date: Tue, 29 Oct 2024 16:29:04 +0100 Subject: [PATCH] Handle ambigous profile/group parameters Introduce the -e group: option, to improve handling of ambigous parameters (such as "security" etc.) --- .../analyzers/config_handler.py | 36 +++++++++++-------- analyzer/codechecker_analyzer/checkers.py | 3 +- analyzer/tests/unit/test_checker_handling.py | 28 ++++++++------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/analyzer/codechecker_analyzer/analyzers/config_handler.py b/analyzer/codechecker_analyzer/analyzers/config_handler.py index bfc8be40fa..6833a63c3e 100644 --- a/analyzer/codechecker_analyzer/analyzers/config_handler.py +++ b/analyzer/codechecker_analyzer/analyzers/config_handler.py @@ -12,8 +12,10 @@ from abc import ABCMeta from enum import Enum +from string import Template import collections import platform +import sys import re from codechecker_analyzer import analyzer_context @@ -211,22 +213,26 @@ def initialize_checkers(self, guidelines = checker_labels.occurring_values('guideline') for identifier, enabled in cmdline_enable: - if ':' in identifier: + if "group:" in identifier: + identifier = identifier.replace("group:", "") + self.set_checker_enabled(identifier, enabled) + elif ':' in identifier: for checker in checker_labels.checkers_by_labels([identifier]): self.set_checker_enabled(checker, enabled) - elif identifier in profiles: - if identifier in reserved_names: - LOG.warning("Profile name '%s' conflicts with a " - "checker(-group) name.", identifier) - for checker in checker_labels.checkers_by_labels( - [f'profile:{identifier}']): - self.set_checker_enabled(checker, enabled) - elif identifier in guidelines: - if identifier in reserved_names: - LOG.warning("Guideline name '%s' conflicts with a " - "checker(-group) name.", identifier) - for checker in checker_labels.checkers_by_labels( - [f'guideline:{identifier}']): - self.set_checker_enabled(checker, enabled) + elif identifier in reserved_names: + templ = Template("The ${entity} name '${identifier}' " + "conflicts with a checker(-group) name. " + "Please use -e ${entity}: to select " + "checkers of a ${entity} or use -e group: " + "to select checkers which have a name " + "starting with '${identifier}'.") + if identifier in profiles: + LOG.error(templ.substitute(entity="profile", + identifier=identifier)) + sys.exit(1) + elif identifier in guidelines: + LOG.error(templ.substitute(entity="guideline", + identifier=identifier)) + sys.exit(1) else: self.set_checker_enabled(identifier, enabled) diff --git a/analyzer/codechecker_analyzer/checkers.py b/analyzer/codechecker_analyzer/checkers.py index 1e9b6f7461..65bc57b031 100644 --- a/analyzer/codechecker_analyzer/checkers.py +++ b/analyzer/codechecker_analyzer/checkers.py @@ -23,7 +23,8 @@ def available(ordered_checkers, available_checkers): if checker_name.startswith('profile:') or \ checker_name.startswith('guideline:') or \ checker_name.startswith('severity:') or \ - checker_name.startswith('sei-cert:'): + checker_name.startswith('sei-cert:') or \ + checker_name.startswith('group:'): continue name_match = False diff --git a/analyzer/tests/unit/test_checker_handling.py b/analyzer/tests/unit/test_checker_handling.py index 7c5dd81db4..569cece6fe 100644 --- a/analyzer/tests/unit/test_checker_handling.py +++ b/analyzer/tests/unit/test_checker_handling.py @@ -154,6 +154,10 @@ def f(checks, checkers): 'alpha.security.ArrayBound', 'alpha.security.MallocOverflow'] + sensitive_profile_alpha = [ + 'alpha.core.BoolAssignment', + 'alpha.core.TestAfterDivZero'] + # "default" profile. default_profile = [ 'security.FloatLoopCounter', @@ -216,10 +220,16 @@ def f(checks, checkers): # Enable "security" profile checkers without "profile:" prefix. cfg_handler = ClangSA.construct_config_handler(args) + with self.assertRaises(SystemExit) as e: + cfg_handler.initialize_checkers(checkers, [('security', True)]) + self.assertEqual(e.exception.code, 1) + + # Enable "sensitive" profile checkers without "profile:" prefix. + cfg_handler = ClangSA.construct_config_handler(args) cfg_handler.initialize_checkers(checkers, - [('security', True)]) + [('sensitive', True)]) self.assertTrue(all_with_status(CheckerState.ENABLED) - (cfg_handler.checks(), security_profile_alpha)) + (cfg_handler.checks(), sensitive_profile_alpha)) self.assertTrue(all_with_status(CheckerState.ENABLED) (cfg_handler.checks(), default_profile)) @@ -232,10 +242,9 @@ def f(checks, checkers): # Enable "sei-cert" guideline checkers. cfg_handler = ClangSA.construct_config_handler(args) - cfg_handler.initialize_checkers(checkers, - [('sei-cert', True)]) - self.assertTrue(all_with_status(CheckerState.ENABLED) - (cfg_handler.checks(), cert_guideline)) + with self.assertRaises(SystemExit) as e: + cfg_handler.initialize_checkers(checkers, [('sei-cert', True)]) + self.assertEqual(e.exception.code, 1) # Disable "sei-cert" guideline checkers. cfg_handler = ClangSA.construct_config_handler(args) @@ -244,13 +253,6 @@ def f(checks, checkers): self.assertTrue(all_with_status(CheckerState.DISABLED) (cfg_handler.checks(), cert_guideline)) - # Disable "sei-cert" guideline checkers. - cfg_handler = ClangSA.construct_config_handler(args) - cfg_handler.initialize_checkers(checkers, - [('sei-cert', False)]) - self.assertTrue(all_with_status(CheckerState.DISABLED) - (cfg_handler.checks(), cert_guideline)) - cfg_handler = ClangSA.construct_config_handler(args) cfg_handler.initialize_checkers(checkers, [('default', False),