Skip to content

Commit f56fa0f

Browse files
committed
Detect invalid deviation markers
1 parent c65f635 commit f56fa0f

File tree

9 files changed

+121
-4
lines changed

9 files changed

+121
-4
lines changed

cpp/common/src/codingstandards/cpp/deviations/CodeIdentifierDeviation.qll

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ abstract class CommentDeviationMarker extends Comment {
7474
DeviationRecord getRecord() { result = record }
7575
}
7676

77+
/**
78+
* A deviation marker in a comment that is not a valid deviation marker.
79+
*/
80+
class InvalidCommentDeviationMarker extends Comment {
81+
InvalidCommentDeviationMarker() {
82+
not this instanceof CommentDeviationMarker and
83+
commentMatches(this, "codeql::" + supportedStandard() + "_deviation")
84+
}
85+
}
86+
7787
/**
7888
* A deviation marker for a deviation that applies to the current line.
7989
*/
@@ -182,9 +192,7 @@ private class BeginStack extends TBeginStack {
182192
}
183193
}
184194

185-
private predicate isDeviationRangePaired(
186-
DeviationRecord record, DeviationBegin begin, DeviationEnd end
187-
) {
195+
predicate isDeviationRangePaired(DeviationRecord record, DeviationBegin begin, DeviationEnd end) {
188196
exists(File file, int index |
189197
record = end.getRecord() and
190198
hasDeviationCommentFileOrdering(record, end, file, index) and
@@ -226,6 +234,21 @@ class DeviationAttribute extends StdAttribute {
226234
}
227235
}
228236

237+
/**
238+
* A deviation attribute that is not associated with any deviation record.
239+
*/
240+
class InvalidDeviationAttribute extends StdAttribute {
241+
string unknownCodeIdentifier;
242+
243+
InvalidDeviationAttribute() {
244+
this.hasQualifiedName("codeql", supportedStandard() + "_deviation") and
245+
"\"" + unknownCodeIdentifier + "\"" = this.getAnArgument().getValueText() and
246+
not exists(DeviationRecord record | record.getCodeIdentifier() = unknownCodeIdentifier)
247+
}
248+
249+
string getAnUnknownCodeIdentifier() { result = unknownCodeIdentifier }
250+
}
251+
229252
newtype TCodeIndentifierDeviation =
230253
TSingleLineDeviation(DeviationRecord record, Comment comment, string filepath, int suppressedLine) {
231254
(
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Invalid deviation dode identifier
2+
3+
## Overview
4+
5+
Invalid deviation markers in code have no effect on the results but may indicate confusion over which results will be suppressed.
6+
7+
Deviation code markers are used to suppress CodeQL Coding Standards results, following the process specified in the "MISRA Compliance 2020" document. There are a range of different deviation markers, with specific syntactic requirements. If those syntactic requirements are not met, the marker is invalid and will not be applied, which is likely contrary to developer expectations.
8+
9+
## Recommendation
10+
11+
Ensure the following requirements are met:
12+
13+
* All `codeql::<standard>_deviation_begin(..)` markers are paired with a matching `codeql::<standard>_deviation_end(..)` marker.
14+
* All instances of `codeql::<standard>_deviation` in comments are correctly formatted comment markers, and reference a `code-identifier`s that is specified in a deviation record included in the analysis.
15+
* All deviation attributes reference `code-identifier`s that are specified in a deviation record included in the analysis.
16+
17+
## References
18+
19+
* [MISRA Compliance 2020 document - Chapter 4.2 (page 12) - Deviations](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @id cpp/coding-standards/invalid-deviation-code-identifiers
3+
* @name Invalid deviation code identifiers
4+
* @description Deviation code identifiers must be valid.
5+
* @kind problem
6+
* @problem.severity error
7+
*/
8+
9+
import cpp
10+
import CodeIdentifierDeviation
11+
12+
predicate deviationCodeIdentifierError(Element e, string message) {
13+
exists(DeviationEnd end |
14+
e = end and
15+
not isDeviationRangePaired(_, _, end) and
16+
message = "Deviation end block is unmatched."
17+
)
18+
or
19+
exists(InvalidDeviationAttribute b |
20+
e = b and
21+
message =
22+
"Deviation attribute references unknown code identifier " + b.getAnUnknownCodeIdentifier() +
23+
"."
24+
)
25+
or
26+
exists(InvalidCommentDeviationMarker m |
27+
e = m and
28+
message =
29+
"Deviation marker does not match an expected format, or references an unknown code identifier."
30+
)
31+
}
32+
33+
from Element e, string message
34+
where deviationCodeIdentifierError(e, message)
35+
select e, message
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| invalidcodeidentifiers.cpp:1:1:1:45 | // codeql::misra_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. |
2+
| invalidcodeidentifiers.cpp:2:1:2:47 | // codeql::autosar_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. |
3+
| invalidcodeidentifiers.cpp:3:1:3:44 | // codeql::cert_deviation(x) - invalid, no x | Deviation marker does not match an expected format, or references an unknown code identifier. |
4+
| invalidcodeidentifiers.cpp:4:1:4:71 | // codeql::misra_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. |
5+
| invalidcodeidentifiers.cpp:5:1:5:73 | // codeql::autosar_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. |
6+
| invalidcodeidentifiers.cpp:6:1:6:70 | // codeql::cert_deviation_next(a-0-4-2-deviation) - invalid, next_line | Deviation marker does not match an expected format, or references an unknown code identifier. |
7+
| invalidcodeidentifiers.cpp:14:1:14:74 | // codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. |
8+
| invalidcodeidentifiers.cpp:15:1:15:76 | // codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. |
9+
| invalidcodeidentifiers.cpp:16:1:16:73 | // codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end | Deviation end block is unmatched. |
10+
| invalidcodeidentifiers.cpp:18:3:18:25 | misra_deviation | Deviation attribute references unknown code identifier x. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
codingstandards/cpp/deviations/InvalidDeviationCodeIdentifier.ql

cpp/common/test/deviations/invalid_deviations/coding-standards.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@
8686
<rule-id>RULE-13-6</rule-id>
8787
<query-id>c/misra/sizeof-operand-with-side-effect</query-id>
8888
</deviations-entry>
89+
<deviations-entry>
90+
<rule-id>A0-4-2</rule-id>
91+
<justification>long double is required for interaction with third-party libraries.</justification>
92+
<code-identifier>a-0-4-2-deviation</code-identifier>
93+
</deviations-entry>
8994
</deviations>
9095
<deviation-permits>
9196
<deviation-permits-entry>

cpp/common/test/deviations/invalid_deviations/coding-standards.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ deviations:
4646
- permit-id: DP2
4747
- rule-id: RULE-13-6
4848
query-id: c/misra/sizeof-operand-with-side-effect
49+
- rule-id: A0-4-2
50+
justification: long double is required for interaction with third-party libraries.
51+
code-identifier: a-0-4-2-deviation
4952
deviation-permits:
5053
- permit-id: DP1
5154
justification: foo bar baz

cpp/common/test/deviations/invalid_deviations/dummy.cpp

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// codeql::misra_deviation(x) - invalid, no x
2+
// codeql::autosar_deviation(x) - invalid, no x
3+
// codeql::cert_deviation(x) - invalid, no x
4+
// codeql::misra_deviation_next(a-0-4-2-deviation) - invalid, next_line
5+
// codeql::autosar_deviation_next(a-0-4-2-deviation) - invalid, next_line
6+
// codeql::cert_deviation_next(a-0-4-2-deviation) - invalid, next_line
7+
8+
// codeql::misra_deviation_begin(a-0-4-2-deviation)
9+
// codeql::autosar_deviation_begin(a-0-4-2-deviation)
10+
// codeql::cert_deviation_begin(a-0-4-2-deviation)
11+
// codeql::misra_deviation_end(a-0-4-2-deviation)
12+
// codeql::autosar_deviation_end(a-0-4-2-deviation)
13+
// codeql::cert_deviation_end(a-0-4-2-deviation)
14+
// codeql::misra_deviation_end(a-0-4-2-deviation) - invalid, unmatched end
15+
// codeql::autosar_deviation_end(a-0-4-2-deviation) - invalid, unmatched end
16+
// codeql::cert_deviation_end(a-0-4-2-deviation) - invalid, unmatched end
17+
18+
[[codeql::misra_deviation("x")]] // invalid
19+
void test() {}
20+
21+
[[codeql::autosar_deviation("a-0-4-2-deviation")]]
22+
void test2() {}

0 commit comments

Comments
 (0)