From af151d715419f40555f4fad0ca0b8a5399fe616d Mon Sep 17 00:00:00 2001 From: swasti16 Date: Tue, 17 Oct 2023 23:48:27 +0530 Subject: [PATCH] Fix #12079: Misra: calling unknown function in condition => false positive 14.4, missing misra-config warning --- addons/cppcheckdata.py | 1 + addons/misra.py | 58 +++++++++++++++-- addons/test/misra/misra-suppressions1-test.c | 4 +- addons/test/misra/misra-test.c | 67 ++++++++++++-------- 4 files changed, 94 insertions(+), 36 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 550d2ea71745..d0d39702b7d6 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -11,6 +11,7 @@ import os import sys import subprocess +import xml.etree.ElementTree as ET try: import pathlib diff --git a/addons/misra.py b/addons/misra.py index 4f37d20413c0..b6cc9d87fb93 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -2805,7 +2805,9 @@ def misra_14_4(self, data): continue if not token.astOperand1 or not (token.astOperand1.str in ['if', 'while']): continue - if not isBoolExpression(token.astOperand2): + if isBoolExpression(token.astOperand2): + continue + if token.astOperand2.valueType: self.reportError(token, 14, 4) def misra_15_1(self, data): @@ -3185,6 +3187,38 @@ def misra_17_3(self, cfg): for w in cfg.clang_warnings: if w['message'].endswith('[-Wimplicit-function-declaration]'): self.reportError(cppcheckdata.Location(w), 17, 3) + for token in cfg.tokenlist: + if token.str not in ["while", "if"]: + continue + if token.next.str != "(": + continue + tok = token.next + while (tok != token.next.link): + if tok.isName and not tok.function and not tok.valueType and tok.next.str == "(" and \ + not tok.next.valueType and not isKeyword(tok.str) and not isStdLibId(tok.str): + self.reportError(tok, 17, 3) + break + tok = tok.next + + def misra_config(self, data): + for token in data.tokenlist: + if token.str not in ["while", "if"]: + continue + if token.next.str != "(": + continue + tok = token.next + while tok != token.next.link: + if tok.str == "(" and tok.isCast: + tok = tok.link + continue + if not tok.isName or tok.function or tok.variable or tok.varId or tok.valueType \ + or tok.next.str == "(" or tok.str in ["EOF"] \ + or isKeyword(tok.str) or isStdLibId(tok.str): + tok = tok.next + continue + errmsg = tok.str + " Variable is unknown" + self.reportError(token, 0, 0, "config") + break def misra_17_6(self, rawTokens): for token in rawTokens: @@ -4093,21 +4127,30 @@ def setSuppressionList(self, suppressionlist): self.addSuppressedRule(ruleNum) - def reportError(self, location, num1, num2): - ruleNum = num1 * 100 + num2 + def reportError(self, location, num1, num2, other_id = None): + if not other_id: + ruleNum = num1 * 100 + num2 + else: + ruleNum = other_id if self.isRuleGloballySuppressed(ruleNum): return if self.settings.verify: - self.verify_actual.append('%s:%d %d.%d' % (location.file, location.linenr, num1, num2)) + if not other_id: + self.verify_actual.append('%s:%d %d.%d' % (location.file, location.linenr, num1, num2)) + else: + self.verify_actual.append('%s:%d %s' % (location.file, location.linenr, other_id)) elif self.isRuleSuppressed(location.file, location.linenr, ruleNum): # Error is suppressed. Ignore self.suppressionStats.setdefault(ruleNum, 0) self.suppressionStats[ruleNum] += 1 return else: - errorId = 'c2012-' + str(num1) + '.' + str(num2) + if not other_id: + errorId = 'c2012-' + str(num1) + '.' + str(num2) + else: + errorId = 'c2012-' + other_id misra_severity = 'Undefined' cppcheck_severity = 'style' if ruleNum in self.ruleTexts: @@ -4293,7 +4336,7 @@ def fillVerifyExpected(verify_expected, tok): rule_re = re.compile(r'[0-9]+\.[0-9]+') if tok.str.startswith('//') and 'TODO' not in tok.str: for word in tok.str[2:].split(' '): - if rule_re.match(word): + if rule_re.match(word) or word == "config": verify_expected.append('%s:%d %s' % (tok.file, tok.linenr, word)) data = cppcheckdata.parsedump(dumpfile) @@ -4431,6 +4474,7 @@ def fillVerifyExpected(verify_expected, tok): self.executeCheck(1701, self.misra_17_1, cfg) self.executeCheck(1702, self.misra_17_2, cfg) self.executeCheck(1703, self.misra_17_3, cfg) + self.misra_config(cfg) if cfgNumber == 0: self.executeCheck(1706, self.misra_17_6, data.rawTokens) self.executeCheck(1707, self.misra_17_7, cfg) @@ -4751,7 +4795,7 @@ def main(): for misra_id in ids: rules_violated[misra_id] = rules_violated.get(misra_id, 0) + 1 print("MISRA rules violated:") - convert = lambda text: int(text) if text.isdigit() else text + convert = lambda text: int(text) if text.isdigit() else 0 misra_sort = lambda key: [convert(c) for c in re.split(r'[\.-]([0-9]*)', key)] for misra_id in sorted(rules_violated.keys(), key=misra_sort): res = re.match(r'misra-c2012-([0-9]+)\\.([0-9]+)', misra_id) diff --git a/addons/test/misra/misra-suppressions1-test.c b/addons/test/misra/misra-suppressions1-test.c index 6c86495ced3c..ce47fe88e955 100644 --- a/addons/test/misra/misra-suppressions1-test.c +++ b/addons/test/misra/misra-suppressions1-test.c @@ -21,13 +21,13 @@ static void foo(void) { for(i = 0; i < 10; i++) { - if(misra_5_2_func3()) //14.4 + if(misra_5_2_func3()) //17.3 { int misra_5_2_var_hides_var_1____31x; int misra_5_2_var_hides_var_1____31y;//5.2 } } - } while(misra_5_2_func2()); //14.4 + } while(misra_5_2_func2()); //17.3 } } } diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 279371d2a37a..f5f7764c733e 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -61,13 +61,13 @@ typedef unsigned long long u64; static void misra_1_2(void) { (void)(condition ? : 0); // 1.2 - a = 1 + ({if (!expr) {code;} 1;}); // 1.2 + a = 1 + ({if (!expr) {code;} 1;}); // 1.2 config } static _Atomic int misra_1_4_var; // 1.4 static _Noreturn void misra_1_4_func(void) // 1.4 { - if (0 != _Generic(misra_1_4_var)) {} // 1.4 + if (0 != _Generic(misra_1_4_var)) {} // 1.4 17.3 printf_s("hello"); // 1.4 } @@ -160,13 +160,13 @@ static void foo(void) { for(i = 0; i < 10; i++) { - if(misra_5_2_func3()) //14.4 + if(misra_5_2_func3()) //17.3 { int misra_5_2_var_hides_var_1____31x; int misra_5_2_var_hides_var_1____31y;//5.2 } } - } while(misra_5_2_func2()); //14.4 + } while(misra_5_2_func2()); //17.3 } break; } @@ -252,11 +252,11 @@ static void misra_5_5_func1(void) { do { - if(misra_5_5_func3()) //14.4 + if(misra_5_5_func3()) //17.3 { int misra_5_5_hides_macro________31y; //5.5 } - } while(misra_5_5_func2()); //14.4 + } while(misra_5_5_func2()); //17.3 } break; } @@ -1144,15 +1144,15 @@ static s13_4_t s13_4 = }; static void misra_13_4(void) { - if (x != (y = z)) {} // 13.4 + if (x != (y = z)) {} // 13.4 config else {} } static void misra_13_5(void) { - if (x && (y++ < 123)){} // 13.5 - if (x || ((y += 19) > 33)){} // 13.5 - if (x || ((y = 25) > 33)){} // 13.5 13.4 - if (x || ((--y) > 33)){} // 13.5 + if (x && (y++ < 123)){} // 13.5 config + if (x || ((y += 19) > 33)){} // 13.5 config + if (x || ((y = 25) > 33)){} // 13.5 13.4 config + if (x || ((--y) > 33)){} // 13.5 config else {} } @@ -1297,13 +1297,16 @@ struct { unsigned int y:1; } r14_4_struct; // 8.4 static void misra_14_4(bool b) { - if (x+4){} // 14.4 + if (x+4){} //config else {} if (b) {} else {} if (r14_4_struct.x) {} + + // #12079 + if (z) {} //config } static void misra_15_1(void) { @@ -1317,22 +1320,22 @@ static void misra_15_2(void) { } static void misra_15_3(void) { - if (x!=0) { + if (x!=0) { //config goto L1; // 15.3 15.1 - if (y!=0) { + if (y!=0) { //config L1: } else {} } else {} switch (x) { case 0: - if (x == y) { + if (x == y) { //config goto L2; // 15.3 15.1 } goto L2; // 15.3 15.1 L3: foo(); - if (a == 0x42) { + if (a == 0x42) { //config // Compliant: goto L3; // 15.1 15.2 } @@ -1432,14 +1435,14 @@ static void misra_15_4(void) { } static int misra_15_5(void) { - if (x!=0) { + if (x!=0) { // config return 1; // 15.5 } else {} return 2; } static void misra_15_6(void) { - if (x!=0); // 15.6 + if (x!=0); // 15.6 config else{} #if A>1 // 20.9 @@ -1454,7 +1457,7 @@ static void misra_15_6(void) { #endif { (void)0; } // no-warning - do {} while (x<0); // no-warning + do {} while (x<0); // config } static void misra_15_6_fp(void) @@ -1474,11 +1477,11 @@ static void misra_15_7(void) { uint32_t var = 0; uint32_t var2 = 0; - if (x!=0){} // no-warning - if (x!=0){} else if(x==1){} // 15.7 - if (x!=0){} else if(x==1){}else{;} // no-warning + if (x!=0){} // config + if (x!=0){} else if(x==1){} // 15.7 config + if (x!=0){} else if(x==1){}else{;} // config - if (x!=0) + if (x!=0) // config { } else @@ -1491,8 +1494,8 @@ static void misra_15_7(void) { } // no-warning } - if (a==2) {} else if (b==4) {} // 15.7 - if (a==2) {} else { if (b==4) {} } // no-warning + if (a==2) {} else if (b==4) {} // 15.7 config + if (a==2) {} else { if (b==4) {} } // no-warning config } static void misra_16_1(int32_t i) { @@ -1511,7 +1514,7 @@ static void misra_16_2(void) { default: break; case 1: - while (y>4) { + while (y>4) { //config case 2: break; // 16.2 } break; @@ -1535,7 +1538,7 @@ static void misra_16_3(void) { a=4; break; case 9: - if (a==b) { + if (a==b) { //config break; } case 10: // 16.3 @@ -1690,6 +1693,16 @@ static void misra_17_2_5(void) { misra_17_2_1(); // no-warning } +bool (*dostuff)(); //8.2 8.4 +static void misra_17_3(void) { + if (dostuff()) {} +} + +static void misra_config(char str) { + if (strlen(str) > 3){} //10.4 + if (sizeof(int) > 1){} //10.4 +} + static void misra_17_6(int x[static 20]) {(void)x;} // 17.6 static int calculation(int x) { return x + 1; }