Skip to content

Commit

Permalink
[bugfix] Allow statisticsbased checker disable
Browse files Browse the repository at this point in the history
When --stats flag is given to then command "CodeChecker analyze" then
two statistics-based checkers are enabled by default:

- statisticsbased.SpecialReturnValue
- statisticsbased.UncheckedReturnValue

These can't be disabled if --stats flag is used.

This patch fixes this bug: now users can disable either statistics-based
checker, even if --stats is used.
  • Loading branch information
bruntib committed Aug 21, 2023
1 parent ed902a6 commit 70cae53
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 21 deletions.
21 changes: 0 additions & 21 deletions analyzer/codechecker_analyzer/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@

from codechecker_common.logger import get_logger

from codechecker_statistics_collector.collectors.special_return_value import \
SpecialReturnValueCollector
from codechecker_statistics_collector.collectors.return_value import \
ReturnValueCollector

from . import analyzer_context, analysis_manager, pre_analysis_manager, \
checkers
from .analyzers import analyzer_types
Expand Down Expand Up @@ -193,22 +188,6 @@ def perform_analysis(args, skip_handlers, actions, metadata_tool,
"'--no-missing-checker-error'")
sys.exit(1)

if 'stats_enabled' in args:
config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
SpecialReturnValueCollector.checker_analyze)

config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
ReturnValueCollector.checker_analyze)

# Statistics collector checkers must be explicitly disabled
# as they trash the output.
if "clangsa" in analyzers:
config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
SpecialReturnValueCollector.checker_collect, False)

config_map[ClangSA.ANALYZER_NAME].set_checker_enabled(
ReturnValueCollector.checker_collect, False)

enabled_checkers = defaultdict(list)

# Save some metadata information.
Expand Down
51 changes: 51 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
from codechecker_common.logger import get_logger

from codechecker_analyzer import analyzer_context, env
from codechecker_statistics_collector.collectors.special_return_value import \
SpecialReturnValueCollector
from codechecker_statistics_collector.collectors.return_value import \
ReturnValueCollector

from .. import analyzer_base
from ..config_handler import CheckerState
Expand Down Expand Up @@ -94,6 +98,19 @@ def parse_clang_help_page(
return res


def _is_user_disabled_checker(checker, ordered_checkers):
"""
This function returns True if the given checker is disabled by the user
explicitly by a --disable flag.
"""
if not ordered_checkers:
return False

disabled_checkers = (c for c, enabled in ordered_checkers if not enabled)

return any(checker.startswith(c) for c in disabled_checkers)


class ClangSA(analyzer_base.SourceAnalyzer):
"""
Constructs clang static analyzer commands.
Expand Down Expand Up @@ -596,6 +613,40 @@ def construct_config_handler(cls, args):
cmdline_checkers,
'enable_all' in args and args.enable_all)

# If --stats flag is provided then enable statistics-based checkers
# unless explicitly disabled by the user.
if 'stats_enabled' in args:
# In some Clang versions, statisticsbased checkers are in the alpha
# package (alpha.statisticsbased), and maybe not in others. Lets
# figure out the actual checker name first.
special_return_value = next((
checker for checker, _ in checkers
if SpecialReturnValueCollector.checker_analyze in checker),
None)
unchecked_return_value = next((
checker for checker, _ in checkers
if ReturnValueCollector.checker_analyze in checker),
None)

if special_return_value and not _is_user_disabled_checker(
special_return_value,
cmdline_checkers):
handler.set_checker_enabled(special_return_value)

if unchecked_return_value and not _is_user_disabled_checker(
unchecked_return_value,
cmdline_checkers):
handler.set_checker_enabled(unchecked_return_value)

# Statistics collector checkers must be explicitly disabled as they
# trash the output. Thise checkers are executed in a preceding analysis
# phase.
handler.set_checker_enabled(
SpecialReturnValueCollector.checker_collect, False)

handler.set_checker_enabled(
ReturnValueCollector.checker_collect, False)

handler.checker_config = []

# TODO: This extra "isinstance" check is needed for
Expand Down
26 changes: 26 additions & 0 deletions analyzer/tests/unit/test_checker_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"""


from distutils import util
import os
import unittest
from argparse import Namespace

Expand Down Expand Up @@ -148,10 +150,15 @@ def f(checks, checkers):
'security.insecureAPI.bcmp',
'alpha.llvm.Conventions']

statisticsbased = [
'statisticsbased.SpecialReturnValue',
'statisticsbased.UncheckedReturnValue']

checkers = []
checkers.extend(map(add_description, security_profile_alpha))
checkers.extend(map(add_description, default_profile))
checkers.extend(map(add_description, cert_guideline))
checkers.extend(map(add_description, statisticsbased))

# "default" profile checkers are enabled explicitly. Others are in
# "default" state.
Expand Down Expand Up @@ -232,6 +239,25 @@ def f(checks, checkers):
self.assertTrue(all_with_status(CheckerState.enabled)
(cfg_handler.checks(), low_severity))

# Test if statisticsbased checkers are enabled by --stats flag
# by default.
stats_capable = bool(util.strtobool(
os.environ.get('CC_TEST_FORCE_STATS_CAPABLE', 'False')))

if stats_capable:
cfg_handler = ClangSA.construct_config_handler(
Namespace(stats_enabled=True))
cfg_handler.initialize_checkers(checkers, [])

enabled_checkers = (
checker for checker, (enabled, _)
in cfg_handler.checks().items()
if enabled == CheckerState.enabled)

for stat_checker in statisticsbased:
self.assertTrue(
any(stat_checker in c for c in enabled_checkers))


def create_analyzer_tidy(args=[]):
cfg_handler = ClangTidy.construct_config_handler(args)
Expand Down

0 comments on commit 70cae53

Please sign in to comment.