Skip to content

Fix #13417 (addons: Line suppressions acts as global suppressions) - #9023

Open
g-chauvel wants to merge 2 commits into
cppcheck-opensource:mainfrom
g-chauvel:addon-line-suppression
Open

g-chauvel wants to merge 2 commits into
cppcheck-opensource:mainfrom
g-chauvel:addon-line-suppression

Conversation

@g-chauvel

Copy link
Copy Markdown
Contributor

The last branch of Suppression.isMatch() in cppcheckdata.py ignores lineNumber since 7e42652 split the condition. So a suppression for one line (--suppress=id:file:line, in a suppression file or inline) hides the id on the whole file. This only happens when the addon is run with python on a dump, cppcheck --addon=misra is not affected.

t.c

void f1(int a) { }
void f2(int b) { }
void f3(int c) { }
cppcheck -q --dump --suppress=misra-c2012-2.7:t.c:1 t.c
python misra.py -q t.c.dump

Before PR:

[t.c:1] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]
[t.c:2] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]
[t.c:3] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]

With PR:

[t.c:2] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-2.7]
[t.c:3] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-2.7]
[t.c:1] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]
[t.c:2] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]
[t.c:3] (style) misra violation (use --rule-texts=<file> to get proper output) (Undefined) [misra-c2012-8.4]

Suppression.isMatch() accepted any suppression without a type in its
last branch, ignoring lineNumber, so --suppress=id:file:line hid the id
on every line of the file when an addon runs outside cppcheck.

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

The fix is correct for the bug it targets: a --suppress=id:file:line suppression no longer applies to the whole file. But it breaks one inline suppression form when the addon is run with Python on a dump.

The form is { // cppcheck-suppress id, with the { alone on its line. For backward compatibility, cppcheck applies this suppression to the comment's line and to the next line (thisAndNextLine in lib/preprocessor.cpp and lib/suppressions.cpp). SuppressionList::dump() does not write thisAndNextLine, so the dump only has lineNumber = the line of the {. Before the PR, the overly broad fallback branch suppressed the warning on the next line, by accident. Now the warning is reported there. Running cppcheck --addon=misra still suppresses it, so the two ways of running the addon now give different results.

To fix this, dump the thisAndNextLine flag and check it in Suppression.isMatch(). That keeps the PR's behaviour for every other case. I found no other problems: line suppressions on the previous line and on the same line still work.

Testing

  • Built cppcheck and testrunner in pr/.
  • Tests: python3 -m pytest test/addon --cppcheck-binary=$PWD/cppcheck gives 115 passed, 2 xfailed. ./testrunner TestSuppressions passes. The test_cppcheckdata.py tests fail with errors unless --cppcheck-binary is given.
  • The case from the PR description behaves as described. Inline suppressions on the previous line (// cppcheck-suppress id on its own line) and on the same line (after the code) still work with the PR.

Regression: { // cppcheck-suppress

t2.c:

int g(int x)
{ // cppcheck-suppress misra-c2012-14.4
    if (x) { return 1; }
    return 0;
}
$ cppcheck -q --inline-suppr --dump t2.c
$ grep suppression t2.c.dump
    <suppression errorId="misra-c2012-14.4" fileName="t2.c" lineNumber="2" inline="true" />
$ python3 pr/addons/misra.py -q t2.c.dump
[t2.c:1] ... [misra-c2012-8.4]
[t2.c:3] ... [misra-c2012-14.4]     <-- new with the PR
[t2.c:3] ... [misra-c2012-15.5]
$ python3 base/addons/misra.py -q t2.c.dump
[t2.c:1] ... [misra-c2012-8.4]
[t2.c:3] ... [misra-c2012-15.5]
$ cppcheck -q --enable=style --addon=misra --inline-suppr t2.c   # cppcheck's own handling
misra-c2012-8.4
misra-c2012-15.5

Automated review of e6774db by Claude. The pull request was built and tested locally.

Comment thread addons/cppcheckdata.py
# Other Suppression (Globally set via suppression file or cli command)
if ((self.fileName is None or fnmatch(file, self.fileName))
and (self.suppressionType is None)
and (self.lineNumber is None)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

This breaks the { // cppcheck-suppress id form (with the { alone on its line). cppcheck applies that suppression to the comment's line and to the next line (thisAndNextLine in lib/preprocessor.cpp and SuppressionList::Suppression::isSuppressed). SuppressionList::dump() does not write thisAndNextLine, so the dump only has lineNumber = the line of the {. Before this PR, this fallback branch suppressed the warning on the next line by accident. Now the addon reports it when run with Python on the dump, while cppcheck --addon=misra --inline-suppr still suppresses it.

Example:

int g(int x)
{ // cppcheck-suppress misra-c2012-14.4
    if (x) { return 1; }
    return 0;
}

With the PR, misra.py on the dump reports [t2.c:3] [misra-c2012-14.4]; the base version does not.

To fix this, add e.g. thisAndNextLine="true" to the dump and in the line-suppression branch also accept int(line) == int(self.lineNumber) + 1 when that flag is set.

cppcheck applies "{ // cppcheck-suppress id" to the comment line and to
the next line. The dump only had lineNumber, so an addon run on the dump
reported the id on the next line. Suppression.isMatch() accepts that
line when thisAndNextLine is set.

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

I found no new problems. The earlier review asked for the { // cppcheck-suppress id form to work again, and it does now: SuppressionList::dump() writes thisAndNextLine="true", and Suppression.isMatch() also accepts the next line when that flag is set. This matches SuppressionList::Suppression::isSuppressed() in C++. A suppression with a line number no longer acts as a whole-file suppression. Suppressions without a line number, file suppressions and block suppressions behave as before. Macro suppressions (type="macro") are still not handled by cppcheckdata.py, but the base version doesn't handle them either, so the PR didn't cause that.

Earlier comments

# Comment By Where Status
1 Fix breaks { // cppcheck-suppress id (thisAndNextLine) suppressions when the addon runs on a dump AI review general ✅ Fixed
2 Dump thisAndNextLine and accept lineNumber+1 in Suppression.isMatch() AI review addons/cppcheckdata.py:1058 ✅ Fixed

Testing

Build: make -j8 cppcheck testrunner in pr/ succeeded.

Tests:

  • ./testrunner TestSuppressions: 0 failures.
  • python3 -m pytest test/addon --cppcheck-binary=$PWD/cppcheck: 116 passed, 2 xfailed. This includes the test that is no longer marked xfail and the new test_line_suppression_this_and_next_line.
  • test/cli/dumpfile_test.py and test/cli/inline-suppress_test.py: 43 passed, 7 skipped, 1 xfailed.
  • PYTHONPATH=addons pytest addons/test (misra and y2038): 25 passed.
  • test/cli/other_test.py has 10 failures, all from the environment: the --rule tests fail because this build has no rules support, and test_redundant_file_reads fails with FileNotFoundError (the tool it needs isn't installed). None of them involve suppressions.

Manual tests (I ran python3 pr/addons/misra.py on each dump):

  • The example from the PR description, with --suppress=misra-c2012-2.7:t.c:1: only line 1 is suppressed, and lines 2 and 3 still report 2.7, as the description says.
  • { // cppcheck-suppress misra-c2012-14.4 with the if on the next line: the dump has lineNumber="2" thisAndNextLine="true" and 14.4 is suppressed. That was the regression reported earlier; it is fixed.
  • The same, but with an empty line between the { line and the if: thisAndNextLine is not dumped and 14.4 is reported on line 4. cppcheck --addon=misra --inline-suppr does the same, so the two ways of running the addon agree.
  • // cppcheck-suppress-macro: the dump has type="macro", and misra.py on the dump still reports the warning. Base behaves the same, so the PR didn't change this.

Automated review of 5ad5b72 by Claude. The pull request was built and tested locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants