diff --git a/change_notes/2024-01-31-exclusion-a16-0-1.md b/change_notes/2024-01-31-exclusion-a16-0-1.md new file mode 100644 index 0000000000..8ff06ba32d --- /dev/null +++ b/change_notes/2024-01-31-exclusion-a16-0-1.md @@ -0,0 +1,2 @@ +`A16-0-1` - `PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql`: + - Exclude all preprocessor elses and also consider elifs separately (ie do not affect valid ifs) but not valid if not meeting the same criteria as an ifdef etc. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql b/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql index a8e1e59839..6a4182d538 100644 --- a/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql +++ b/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql @@ -21,13 +21,26 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.FunctionLikeMacro +class PermittedInnerDirectiveType extends PreprocessorDirective { + PermittedInnerDirectiveType() { + //permissive listing for directives that can be used in a valid wrapper + this instanceof MacroWrapper or + this instanceof PreprocessorEndif or + this instanceof Include or + this instanceof PermittedMacro or + this instanceof PreprocessorElif or + this instanceof PreprocessorElse + } +} + class PermittedDirectiveType extends PreprocessorDirective { PermittedDirectiveType() { //permissive listing in case directive types modelled in ql ever expands (example non valid directives) this instanceof MacroWrapper or this instanceof PreprocessorEndif or this instanceof Include or - this instanceof PermittedMacro + this instanceof PermittedMacro or + this instanceof PreprocessorElse } } @@ -40,9 +53,9 @@ pragma[noinline] predicate isPreprocConditionalRange( PreprocessorBranch pb, string filepath, int startLine, int endLine ) { - exists(PreprocessorEndif end | pb.getEndIf() = end | - isPreprocFileAndLine(pb, filepath, startLine) and - isPreprocFileAndLine(end, filepath, endLine) + isPreprocFileAndLine(pb, filepath, startLine) and + exists(PreprocessorDirective end | + pb.getNext() = end and isPreprocFileAndLine(end, filepath, endLine) ) } @@ -73,7 +86,7 @@ class MacroWrapper extends PreprocessorIfndef { class AcceptableWrapper extends PreprocessorBranch { AcceptableWrapper() { forall(Element inner | not inner instanceof Comment and this = getAGuard(inner) | - inner instanceof PermittedDirectiveType + inner instanceof PermittedInnerDirectiveType ) } } diff --git a/cpp/autosar/test/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.expected b/cpp/autosar/test/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.expected index 5f6114bea8..44dd686b23 100644 --- a/cpp/autosar/test/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.expected +++ b/cpp/autosar/test/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.expected @@ -2,3 +2,7 @@ | test.cpp:9:1:9:26 | #define OBJECTLIKE_MACRO 1 | Preprocessor directive used for conditional compilation. | | test.cpp:10:1:10:35 | #define FUNCTIONLIKE_MACRO(X) X + 1 | Preprocessor directive used for conditional compilation. | | test.cpp:11:1:11:37 | #define FUNCTIONLIKE_MACROTWO() 1 + 1 | Preprocessor directive used for conditional compilation. | +| test.cpp:31:1:31:26 | #elif OBJECTLIKE_MACRO > 0 | Preprocessor directive used for conditional compilation. | +| test.cpp:37:1:37:26 | #elif OBJECTLIKE_MACRO > 0 | Preprocessor directive used for conditional compilation. | +| test.cpp:41:1:41:23 | #ifdef OBJECTLIKE_MACRO | Preprocessor directive used for conditional compilation. | +| test.cpp:58:1:58:27 | #elif MACRO_ENABLED_OTHER_1 | Preprocessor directive used for conditional compilation. | diff --git a/cpp/autosar/test/rules/A16-0-1/options b/cpp/autosar/test/rules/A16-0-1/options new file mode 100644 index 0000000000..9c0e6cf7b5 --- /dev/null +++ b/cpp/autosar/test/rules/A16-0-1/options @@ -0,0 +1 @@ +semmle-extractor-options:--clang -std=c++14 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../../cpp/common/test/includes/standard-library -D MACRO_ENABLED_NON_1 -D MACRO_ENABLED_OTHER_1 diff --git a/cpp/autosar/test/rules/A16-0-1/test.cpp b/cpp/autosar/test/rules/A16-0-1/test.cpp index b1ee540032..a8b83e40ec 100644 --- a/cpp/autosar/test/rules/A16-0-1/test.cpp +++ b/cpp/autosar/test/rules/A16-0-1/test.cpp @@ -17,3 +17,59 @@ int g; #ifndef TESTHEADER // COMPLIANT #include //COMPLIANT #endif // COMPLIANT + +#ifdef MACRO_ENABLED // COMPLIANT +#include // COMPLIANT +#else // COMPLIANT +#include // COMPLIANT +#endif // COMPLIANT + +#ifdef MACRO_ENABLED_NON // COMPLIANT +#include // COMPLIANT +#elif MACRO_ENABLED_OTHER // COMPLIANT +#include // COMPLIANT +#elif OBJECTLIKE_MACRO > 0 // NON_COMPLIANT +int x00 = 1; // present +#endif // COMPLIANT + +#ifdef OBJECTLIKE_MACRO_NO // COMPLIANT +int x0 = 0; // not present +#elif OBJECTLIKE_MACRO > 0 // NON_COMPLIANT +int x0 = 1; // present +#endif // COMPLIANT + +#ifdef OBJECTLIKE_MACRO // NON_COMPLIANT +int x1 = 0; // present +#elif OBJECTLIKE_MACRO > -1 // NON_COMPLIANT[FALSE_NEGATIVE] - known due to + // database not containing elements +int x1 = 1; // not present +#endif // COMPLIANT + +// case 1 - first present only +#ifdef MACRO_ENABLED_NON_1 // COMPLIANT +#include //present +#elif MACRO_ENABLED_OTHER // NON_COMPLIANT[FALSE_NEGATIVE] +int x = 1; // not present +#endif + +// case 2 - second present only +#ifdef MACRO_ENABLED_NON // COMPLIANT +#include //not present +#elif MACRO_ENABLED_OTHER_1 // NON_COMPLIANT +int x = 1; // present +#endif + +// case 3 - neither present +#ifdef MACRO_ENABLED_NON // COMPLIANT +#include //not present +#elif MACRO_ENABLED_OTHER // NON_COMPLIANT[FALSE_NEGATIVE] +int x = 1; // not present +#endif + +// case 4 - both look present but the second still not bc the condition is not +// required to be evaluated +#ifdef MACRO_ENABLED_NON_1 // COMPLIANT +#include //present +#elif MACRO_ENABLED_OTHER_1 // NON_COMPLIANT[FALSE_NEGATIVE] +int x = 1; // not present +#endif \ No newline at end of file