From 3442fc281eb16530c644eec148b6478b0b310a07 Mon Sep 17 00:00:00 2001 From: wienans Date: Tue, 27 Feb 2024 16:51:24 +0100 Subject: [PATCH 1/4] Dump file add additional suppression info --- addons/cppcheckdata.py | 20 +++++++++++++++++++- lib/suppressions.cpp | 5 +++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index e71d444a0b6..f1d7730e37d 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -946,18 +946,27 @@ class Suppression: fileName The name of the file to suppress warnings for, can include wildcards lineNumber The number of the line to suppress warnings from, can be 0 to represent any line symbolName The name of the symbol to match warnings for, can include wildcards + lineBegin The first line to suppress warnings from + lineEnd The last line to suppress warnings from + suppressionType The type of suppression which is applied (unique = 0, file = 1, block = 2, blockBegin = 3, blockEnd = 4, macro = 5) """ errorId = None fileName = None lineNumber = None symbolName = None + lineBegin = None + lineEnd = None + suppressionType = None def __init__(self, element): self.errorId = element.get('errorId') self.fileName = element.get('fileName') self.lineNumber = element.get('lineNumber') self.symbolName = element.get('symbolName') + self.lineBegin = element.get('lineBegin') + self.lineEnd = element.get('lineEnd') + self.suppressionType = element.get('type') def __repr__(self): attrs = ['errorId' , "fileName", "lineNumber", "symbolName"] @@ -967,8 +976,17 @@ def __repr__(self): ) def isMatch(self, file, line, message, errorId): + # Global and Line Suppression if ((self.fileName is None or fnmatch(file, self.fileName)) - and (self.lineNumber is None or int(line) == int(self.lineNumber)) + and (self.lineNumber is None or int(self.suppressionType) == 1 or int(line) == int(self.lineNumber)) + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # Block Suppression Mode + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (int(self.suppressionType) == 2) # Type for Block suppression + and (int(line) > int(self.lineBegin)) # Code Match is between the Block suppression + and (int(line) < int(self.lineEnd)) # Code Match is between the Block suppression and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index 80e922490ea..173cf145b70 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -455,6 +455,11 @@ void SuppressionList::dump(std::ostream & out) const out << " symbolName=\"" << ErrorLogger::toxml(suppression.symbolName) << '\"'; if (suppression.hash > 0) out << " hash=\"" << suppression.hash << '\"'; + if (suppression.lineBegin != Suppression::NO_LINE) + out << " lineBegin=\"" << suppression.lineBegin << '"'; + if (suppression.lineEnd != Suppression::NO_LINE) + out << " lineEnd=\"" << suppression.lineEnd << '"'; + out << " type=\"" << (int) suppression.type << '"'; out << " />" << std::endl; } out << " " << std::endl; From 238d8bc971035d1f7e7dfc32bb3dad64cfee1aa0 Mon Sep 17 00:00:00 2001 From: wienans Date: Wed, 28 Feb 2024 16:29:43 +0100 Subject: [PATCH 2/4] Fix #12477 use strings as types --- addons/cppcheckdata.py | 21 ++++++++++++++------- lib/suppressions.cpp | 11 ++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index f1d7730e37d..9d53a2f6d99 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -948,7 +948,7 @@ class Suppression: symbolName The name of the symbol to match warnings for, can include wildcards lineBegin The first line to suppress warnings from lineEnd The last line to suppress warnings from - suppressionType The type of suppression which is applied (unique = 0, file = 1, block = 2, blockBegin = 3, blockEnd = 4, macro = 5) + suppressionType The type of suppression which is applied (unique = None (default), file, block, blockBegin, blockEnd, macro) """ errorId = None @@ -969,24 +969,31 @@ def __init__(self, element): self.suppressionType = element.get('type') def __repr__(self): - attrs = ['errorId' , "fileName", "lineNumber", "symbolName"] + attrs = ["errorId", "fileName", "lineNumber", "symbolName", "lineBegin", "lineEnd","suppressionType"] return "{}({})".format( "Suppression", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) ) def isMatch(self, file, line, message, errorId): - # Global and Line Suppression + # Line Suppression if ((self.fileName is None or fnmatch(file, self.fileName)) - and (self.lineNumber is None or int(self.suppressionType) == 1 or int(line) == int(self.lineNumber)) + and (self.suppressionType == None) # Verify use of default suppression type (None = unique) + and (self.lineNumber != None and int(line) == int(self.lineNumber)) + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # Global Suppression + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType != None and self.suppressionType == "file") # Verify use of file (global) suppression type and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True # Block Suppression Mode if ((self.fileName is None or fnmatch(file, self.fileName)) - and (int(self.suppressionType) == 2) # Type for Block suppression - and (int(line) > int(self.lineBegin)) # Code Match is between the Block suppression - and (int(line) < int(self.lineEnd)) # Code Match is between the Block suppression + and (self.suppressionType != None and self.suppressionType == "block") # Type for Block suppression + and (self.lineBegin != None and int(line) > int(self.lineBegin)) # Code Match is between the Block suppression + and (self.lineEnd != None and int(line) < int(self.lineEnd)) # Code Match is between the Block suppression and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index 173cf145b70..69bbe95229f 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -459,7 +459,16 @@ void SuppressionList::dump(std::ostream & out) const out << " lineBegin=\"" << suppression.lineBegin << '"'; if (suppression.lineEnd != Suppression::NO_LINE) out << " lineEnd=\"" << suppression.lineEnd << '"'; - out << " type=\"" << (int) suppression.type << '"'; + if (suppression.type == SuppressionList::Type::file) + out << " type=\"file\""; + else if (suppression.type == SuppressionList::Type::block) + out << " type=\"block\""; + else if (suppression.type == SuppressionList::Type::blockBegin) + out << " type=\"blockBegin\""; + else if (suppression.type == SuppressionList::Type::blockEnd) + out << " type=\"blockEnd\""; + else if (suppression.type == SuppressionList::Type::macro) + out << " type=\"macro\""; out << " />" << std::endl; } out << " " << std::endl; From c29f8ed0541a98ae411cd3911a1ded3833d6af01 Mon Sep 17 00:00:00 2001 From: wienans Date: Wed, 28 Feb 2024 18:03:40 +0100 Subject: [PATCH 3/4] Fix suppression file excludes and misra test with inline suppress --- addons/cppcheckdata.py | 8 +++++++- addons/test/misra/misra-suppressions1-test.c | 4 ++++ addons/test/misra/misra-suppressions2-test.c | 1 + addons/test/misra/suppressions.txt | 3 --- addons/test/misra_test.py | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 9d53a2f6d99..80f97c720de 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -983,7 +983,7 @@ def isMatch(self, file, line, message, errorId): and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True - # Global Suppression + # File Suppression if ((self.fileName is None or fnmatch(file, self.fileName)) and (self.suppressionType != None and self.suppressionType == "file") # Verify use of file (global) suppression type and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) @@ -997,6 +997,12 @@ def isMatch(self, file, line, message, errorId): and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True + # Other Suppression (Globaly set via suppression file or cli command) + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType is None) + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True return False diff --git a/addons/test/misra/misra-suppressions1-test.c b/addons/test/misra/misra-suppressions1-test.c index ce47fe88e95..403d71f73ea 100644 --- a/addons/test/misra/misra-suppressions1-test.c +++ b/addons/test/misra/misra-suppressions1-test.c @@ -4,6 +4,7 @@ // This needs to stay at line number 7 to make the test pass // If it is changed update suppressions.txt with the new line number +// cppcheck-suppress-file misra-c2012-5.2 #include //21.6 extern int misra_5_2_var_hides_var______31x;//8.4 @@ -13,6 +14,8 @@ static void misra_5_2_function_hides_var_31y(void) {}//5.2 static void foo(void) { int i; + // cppcheck-suppress-begin misra-c2012-16.4 + // cppcheck-suppress misra-c2012-16.6 switch(misra_5_2_func1()) //16.4 16.6 { case 1: @@ -30,4 +33,5 @@ static void foo(void) } while(misra_5_2_func2()); //17.3 } } + // cppcheck-suppress-end misra-c2012-16.4 } diff --git a/addons/test/misra/misra-suppressions2-test.c b/addons/test/misra/misra-suppressions2-test.c index e32e2ab9781..79d3f68191e 100644 --- a/addons/test/misra/misra-suppressions2-test.c +++ b/addons/test/misra/misra-suppressions2-test.c @@ -2,6 +2,7 @@ // ../../cppcheck --suppressions-list=suppressions.txt --dump misra-suppressions*-test.c && python ../misra.py misra-suppressions*-test.c.dump // There should be no violations reported +// cppcheck-suppress-file misra-c2012-5.2 union misra_5_2_field_hides_field__63x { //19.2 int misra_5_2_field_hides_field__31x; int misra_5_2_field_hides_field__31y;//5.2 diff --git a/addons/test/misra/suppressions.txt b/addons/test/misra/suppressions.txt index 97b070025bd..139e088552e 100644 --- a/addons/test/misra/suppressions.txt +++ b/addons/test/misra/suppressions.txt @@ -1,9 +1,6 @@ misra-c2012-21.6:*/misra-suppressions1-test.c:7 misra-c2012-17.3 -misra-c2012-5.2 misra-c2012-8.4:*/misra-suppressions1-test.c -misra-c2012-16.4:*/misra-suppressions1-test.c -misra-c2012-16.6:*/misra-suppressions1-test.c misra-c2012-4.1:*/misra-suppressions2-test.c misra-c2012-8.4:*/misra-suppressions2-test.c misra-c2012-19.2:*/misra-suppressions2-test.c diff --git a/addons/test/misra_test.py b/addons/test/misra_test.py index 3ae6380b8ad..134599309f6 100644 --- a/addons/test/misra_test.py +++ b/addons/test/misra_test.py @@ -122,7 +122,7 @@ def test_rules_suppression(checker, capsys): for src in test_sources: re_suppressed= r"\[%s\:[0-9]+\]" % src dump_remove(src) - dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt") + dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt --inline-suppr") checker.parseDump(src + ".dump") captured = capsys.readouterr().err found = re.search(re_suppressed, captured) From 5834d306eb653318cc17571bcd7361cff1532cff Mon Sep 17 00:00:00 2001 From: wienans Date: Wed, 28 Feb 2024 18:36:30 +0100 Subject: [PATCH 4/4] Update for inline suppressions --- addons/test/misra_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/test/misra_test.py b/addons/test/misra_test.py index 134599309f6..546b075a709 100644 --- a/addons/test/misra_test.py +++ b/addons/test/misra_test.py @@ -122,7 +122,7 @@ def test_rules_suppression(checker, capsys): for src in test_sources: re_suppressed= r"\[%s\:[0-9]+\]" % src dump_remove(src) - dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt --inline-suppr") + dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt","--inline-suppr") checker.parseDump(src + ".dump") captured = capsys.readouterr().err found = re.search(re_suppressed, captured)