Skip to content

Commit cbec99e

Browse files
Merge branch 'main' into michaelrfairhurst/preconditions-rule-22-3-1-no-asserts-on-constants
2 parents 3d71876 + 3c3f5a3 commit cbec99e

22 files changed

+762
-10
lines changed

.github/workflows/code-scanning-pack-gen.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ jobs:
111111
zip -r codeql-coding-standards/code-scanning-cpp-query-pack.zip codeql-coding-standards/c/ codeql-coding-standards/cpp/ codeql-coding-standards/.codeqlmanifest.json codeql-coding-standards/supported_codeql_configs.json codeql-coding-standards/scripts/configuration codeql-coding-standards/scripts/reports codeql-coding-standards/scripts/shared codeql-coding-standards/scripts/guideline_recategorization codeql-coding-standards/schemas
112112
113113
- name: Upload GHAS Query Pack
114-
uses: actions/upload-artifact@v6
114+
uses: actions/upload-artifact@v7
115115
with:
116116
name: code-scanning-cpp-query-pack.zip
117117
path: code-scanning-cpp-query-pack.zip
@@ -132,7 +132,7 @@ jobs:
132132
codeql pack bundle --output=report-coding-standards.tgz cpp/report/src
133133
134134
- name: Upload qlpack bundles
135-
uses: actions/upload-artifact@v6
135+
uses: actions/upload-artifact@v7
136136
with:
137137
name: coding-standards-codeql-packs
138138
path: '*-coding-standards.tgz'

.github/workflows/codeql_unit_tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ jobs:
153153
file.close()
154154
155155
- name: Upload test results
156-
uses: actions/upload-artifact@v6
156+
uses: actions/upload-artifact@v7
157157
with:
158158
name: ${{ matrix.language }}-test-results-${{ runner.os }}-${{ matrix.codeql_cli }}-${{ matrix.codeql_standard_library_ident }}
159159
path: |
@@ -173,7 +173,7 @@ jobs:
173173
script: |
174174
core.setFailed('Test run job failed')
175175
- name: Collect test results
176-
uses: actions/download-artifact@v7
176+
uses: actions/download-artifact@v8
177177

178178
- name: Validate test results
179179
run: |

.github/workflows/extra-rule-validation.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ jobs:
4646
run: scripts/util/Test-SharedImplementationsHaveTestCases.ps1 -Language c -CIMode
4747

4848

49-
- uses: actions/upload-artifact@v6
49+
- uses: actions/upload-artifact@v7
5050
if: failure()
5151
with:
5252
name: missing-test-report.csv
5353
path: MissingTestReport*.csv
5454

55-
- uses: actions/upload-artifact@v6
55+
- uses: actions/upload-artifact@v7
5656
if: failure()
5757
with:
5858
name: test-report.csv

.github/workflows/generate-html-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
python scripts/documentation/generate_iso26262_docs.py coding-standards-html-docs
3838
3939
- name: Upload HTML documentation
40-
uses: actions/upload-artifact@v6
40+
uses: actions/upload-artifact@v7
4141
with:
4242
name: coding-standards-docs-${{ github.sha }}
4343
path: coding-standards-html-docs/

.github/workflows/standard_library_upgrade_tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ jobs:
145145
}, test_summary_file)
146146
147147
- name: Upload test results
148-
uses: actions/upload-artifact@v6
148+
uses: actions/upload-artifact@v7
149149
with:
150150
name: test-results-${{runner.os}}-${{matrix.codeql_cli}}-${{matrix.codeql_standard_library_ident}}
151151
path: |
@@ -164,7 +164,7 @@ jobs:
164164
python-version: "3.9"
165165

166166
- name: Collect test results
167-
uses: actions/download-artifact@v7
167+
uses: actions/download-artifact@v8
168168

169169
- name: Validate test results
170170
shell: python

cpp/common/src/codingstandards/cpp/Macro.qll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,49 @@ class FunctionLikeMacro extends Macro {
2626
exists(this.getBody().regexpFind("\\#?\\b" + parameter + "\\b", _, result))
2727
)
2828
}
29+
30+
/**
31+
* Holds if the parameter is used in a way that may make it vulnerable to precedence issues.
32+
*
33+
* Typically, parameters are wrapped in parentheses to protect them from precedence issues, but
34+
* that is not always possible.
35+
*/
36+
predicate parameterPrecedenceUnprotected(int index) {
37+
// Check if the parameter is used in a way that requires parentheses
38+
exists(string parameter | parameter = getParameter(index) |
39+
// Finds any occurence of the parameter that is not preceded by, or followed by, either a
40+
// parenthesis or the '#' token operator.
41+
//
42+
// Note the following cases:
43+
// - "(x + 1)" is preceded by a parenthesis, but not followed by one, so SHOULD be matched.
44+
// - "x # 1" is followed by "#" (though not preceded by #) and SHOULD be matched.
45+
// - "(1 + x)" is followed by a parenthesis, but not preceded by one, so SHOULD be matched.
46+
// - "1 # x" is preceded by "#" (though not followed by #) and SHOULD NOT be matched.
47+
//
48+
// So the regex is structured as follows:
49+
// - paramMatch: Matches the parameter at a word boundary, with optional whitespace
50+
// - notHashed: Finds parameters not used with a leading # operator.
51+
// - The final regex finds cases of `notHashed` that are not preceded by a parenthesis,
52+
// and cases of `notHashed` that are not followed by a parenthesis.
53+
//
54+
// Therefore, a parameter with parenthesis on both sides is not matched, a parameter with
55+
// parenthesis missing on one or both sides is only matched if there is no leading or trailing
56+
// ## operator.
57+
exists(string noBeforeParen, string noAfterParen, string paramMatch, string notHashed |
58+
// Not preceded by a parenthesis
59+
noBeforeParen = "(?<!\\(\\s*)" and
60+
// Not followed by a parenthesis
61+
noAfterParen = "(?!\\s*\\))" and
62+
// Parameter at word boundary in optional whitespace
63+
paramMatch = "\\s*\\b" + parameter + "\\b\\s*" and
64+
// A parameter is #'d if it is preceded or followed by the # or ## operators.
65+
notHashed = "(?<!#)" + paramMatch and
66+
// Parameter is used without a leading or trailing parenthesis, and without #.
67+
getBody()
68+
.regexpMatch(".*(" + noBeforeParen + notHashed + "|" + notHashed + noAfterParen + ").*")
69+
)
70+
)
71+
}
2972
}
3073

3174
newtype TMacroOperator =

cpp/common/src/codingstandards/cpp/MatchingParenthesis.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ module MatchingParenthesis<InputString Input> {
6161
occurrence = prevOccurrence + 1
6262
) else (
6363
token = TNotParen() and
64-
exists(inputStr.regexpFind("\\(|\\)", prevOccurrence + 1, endPos)) and
64+
exists(inputStr.regexpFind("\\(|\\)|$", prevOccurrence + 1, endPos)) and
6565
occurrence = prevOccurrence
6666
)
6767
)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype Preprocessor2Query =
7+
TInvalidIncludeDirectiveQuery() or
8+
TUnparenthesizedMacroArgumentQuery() or
9+
TDisallowedUseOfPragmaQuery()
10+
11+
predicate isPreprocessor2QueryMetadata(Query query, string queryId, string ruleId, string category) {
12+
query =
13+
// `Query` instance for the `invalidIncludeDirective` query
14+
Preprocessor2Package::invalidIncludeDirectiveQuery() and
15+
queryId =
16+
// `@id` for the `invalidIncludeDirective` query
17+
"cpp/misra/invalid-include-directive" and
18+
ruleId = "RULE-19-2-2" and
19+
category = "required"
20+
or
21+
query =
22+
// `Query` instance for the `unparenthesizedMacroArgument` query
23+
Preprocessor2Package::unparenthesizedMacroArgumentQuery() and
24+
queryId =
25+
// `@id` for the `unparenthesizedMacroArgument` query
26+
"cpp/misra/unparenthesized-macro-argument" and
27+
ruleId = "RULE-19-3-4" and
28+
category = "required"
29+
or
30+
query =
31+
// `Query` instance for the `disallowedUseOfPragma` query
32+
Preprocessor2Package::disallowedUseOfPragmaQuery() and
33+
queryId =
34+
// `@id` for the `disallowedUseOfPragma` query
35+
"cpp/misra/disallowed-use-of-pragma" and
36+
ruleId = "RULE-19-6-1" and
37+
category = "advisory"
38+
}
39+
40+
module Preprocessor2Package {
41+
Query invalidIncludeDirectiveQuery() {
42+
//autogenerate `Query` type
43+
result =
44+
// `Query` type for `invalidIncludeDirective` query
45+
TQueryCPP(TPreprocessor2PackageQuery(TInvalidIncludeDirectiveQuery()))
46+
}
47+
48+
Query unparenthesizedMacroArgumentQuery() {
49+
//autogenerate `Query` type
50+
result =
51+
// `Query` type for `unparenthesizedMacroArgument` query
52+
TQueryCPP(TPreprocessor2PackageQuery(TUnparenthesizedMacroArgumentQuery()))
53+
}
54+
55+
Query disallowedUseOfPragmaQuery() {
56+
//autogenerate `Query` type
57+
result =
58+
// `Query` type for `disallowedUseOfPragma` query
59+
TQueryCPP(TPreprocessor2PackageQuery(TDisallowedUseOfPragmaQuery()))
60+
}
61+
}

cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import Preconditions1
6868
import Preconditions3
6969
import Preconditions4
7070
import Preprocessor
71+
import Preprocessor2
7172
import Representation
7273
import Scope
7374
import SideEffects1
@@ -155,6 +156,7 @@ newtype TCPPQuery =
155156
TPreconditions3PackageQuery(Preconditions3Query q) or
156157
TPreconditions4PackageQuery(Preconditions4Query q) or
157158
TPreprocessorPackageQuery(PreprocessorQuery q) or
159+
TPreprocessor2PackageQuery(Preprocessor2Query q) or
158160
TRepresentationPackageQuery(RepresentationQuery q) or
159161
TScopePackageQuery(ScopeQuery q) or
160162
TSideEffects1PackageQuery(SideEffects1Query q) or
@@ -242,6 +244,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
242244
isPreconditions3QueryMetadata(query, queryId, ruleId, category) or
243245
isPreconditions4QueryMetadata(query, queryId, ruleId, category) or
244246
isPreprocessorQueryMetadata(query, queryId, ruleId, category) or
247+
isPreprocessor2QueryMetadata(query, queryId, ruleId, category) or
245248
isRepresentationQueryMetadata(query, queryId, ruleId, category) or
246249
isScopeQueryMetadata(query, queryId, ruleId, category) or
247250
isSideEffects1QueryMetadata(query, queryId, ruleId, category) or
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @id cpp/misra/invalid-include-directive
3+
* @name RULE-19-2-2: The #include directive shall be followed by either a <filename> or "filename" sequence
4+
* @description Include directives shall only use the <filename> or "filename" forms.
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity warning
8+
* @tags external/misra/id/rule-19-2-2
9+
* scope/single-translation-unit
10+
* maintainability
11+
* readability
12+
* external/misra/enforcement/decidable
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
19+
from Include include
20+
where
21+
not isExcluded(include, Preprocessor2Package::invalidIncludeDirectiveQuery()) and
22+
// Check for < followed by (not >)+ followed by >, or " followed by (not ")+ followed by ".
23+
not include.getIncludeText().trim().regexpMatch("^(<[^>]+>|\"[^\"]+\")$")
24+
select include, "Non-compliant #include directive text '" + include.getHead() + "'."

0 commit comments

Comments
 (0)