Skip to content

Commit 9e62570

Browse files
Import EXP51-CPP into rule 4-1-3 as it is UB
1 parent d7d4769 commit 9e62570

File tree

14 files changed

+148
-39
lines changed

14 files changed

+148
-39
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `EXP51-CPP` - `DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql`:
2+
- Refactored query logic into a shared library (`DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared.qll`) to enable reuse by MISRA C++ `RULE-4-1-3`. The query logic is unchanged and no visible changes to results or performance are expected.
3+
- The query now uses a `query predicate problems` instead of a `from/where/select`. In path-problem BQRS output, the results section header changes from `#select` to `problems`. Alert results and their content are otherwise identical.

cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.ql

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,18 @@
1818

1919
import cpp
2020
import codingstandards.cpp.cert
21-
import semmle.code.cpp.dataflow.DataFlow
22-
import AllocationToDeleteFlow::PathGraph
21+
import codingstandards.cpp.rules.donotdeleteanarraythroughapointeroftheincorrecttypeshared.DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared
2322

24-
module AllocationToDeleteConfig implements DataFlow::ConfigSig {
25-
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NewArrayExpr }
26-
27-
predicate isSink(DataFlow::Node sink) {
28-
exists(DeleteArrayExpr dae | dae.getExpr() = sink.asExpr())
23+
module DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeConfig implements
24+
DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeSharedConfigSig
25+
{
26+
Query getQuery() {
27+
result = FreedPackage::doNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeQuery()
2928
}
3029
}
3130

32-
module AllocationToDeleteFlow = DataFlow::Global<AllocationToDeleteConfig>;
31+
module Shared =
32+
DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared<DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeConfig>;
3333

34-
from
35-
AllocationToDeleteFlow::PathNode source, AllocationToDeleteFlow::PathNode sink,
36-
NewArrayExpr newArray, DeleteArrayExpr deleteArray
37-
where
38-
not isExcluded(deleteArray.getExpr(),
39-
FreedPackage::doNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeQuery()) and
40-
AllocationToDeleteFlow::flowPath(source, sink) and
41-
newArray = source.getNode().asExpr() and
42-
deleteArray.getExpr() = sink.getNode().asExpr() and
43-
not newArray.getType().getUnspecifiedType() = deleteArray.getExpr().getType().getUnspecifiedType()
44-
select sink, source, sink,
45-
"Array of type " + newArray.getType() + " is deleted through a pointer of type " +
46-
deleteArray.getExpr().getType() + "."
34+
import Shared::PathGraph
35+
import Shared

cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.expected

Lines changed: 0 additions & 15 deletions
This file was deleted.

cpp/cert/test/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp/common/test/rules/donotdeleteanarraythroughapointeroftheincorrecttypeshared/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared.ql

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ newtype UndefinedQuery =
88
TCriticalUnspecifiedBehaviorQuery() or
99
TUndefinedBehaviorAuditQuery() or
1010
TCriticalUnspecifiedBehaviorAuditQuery() or
11-
TPossibleDataRaceBetweenThreadsQuery()
11+
TPossibleDataRaceBetweenThreadsQuery() or
12+
TArrayDeletedThroughPointerOfIncorrectTypeQuery()
1213

1314
predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, string category) {
1415
query =
@@ -55,6 +56,15 @@ predicate isUndefinedQueryMetadata(Query query, string queryId, string ruleId, s
5556
"cpp/misra/possible-data-race-between-threads" and
5657
ruleId = "RULE-4-1-3" and
5758
category = "required"
59+
or
60+
query =
61+
// `Query` instance for the `arrayDeletedThroughPointerOfIncorrectType` query
62+
UndefinedPackage::arrayDeletedThroughPointerOfIncorrectTypeQuery() and
63+
queryId =
64+
// `@id` for the `arrayDeletedThroughPointerOfIncorrectType` query
65+
"cpp/misra/array-deleted-through-pointer-of-incorrect-type" and
66+
ruleId = "RULE-4-1-3" and
67+
category = "required"
5868
}
5969

6070
module UndefinedPackage {
@@ -92,4 +102,11 @@ module UndefinedPackage {
92102
// `Query` type for `possibleDataRaceBetweenThreads` query
93103
TQueryCPP(TUndefinedPackageQuery(TPossibleDataRaceBetweenThreadsQuery()))
94104
}
105+
106+
Query arrayDeletedThroughPointerOfIncorrectTypeQuery() {
107+
//autogenerate `Query` type
108+
result =
109+
// `Query` type for `arrayDeletedThroughPointerOfIncorrectType` query
110+
TQueryCPP(TUndefinedPackageQuery(TArrayDeletedThroughPointerOfIncorrectTypeQuery()))
111+
}
95112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Provides a configurable module DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared
3+
* with a `problems` predicate for the following issue:
4+
* Deleting an array through a pointer of an incorrect type leads to undefined behavior.
5+
*/
6+
7+
import cpp
8+
import codingstandards.cpp.Customizations
9+
import codingstandards.cpp.Exclusions
10+
import semmle.code.cpp.dataflow.DataFlow
11+
12+
signature module DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeSharedConfigSig {
13+
Query getQuery();
14+
}
15+
16+
module DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared<
17+
DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeSharedConfigSig Config>
18+
{
19+
private module AllocationToDeleteConfig implements DataFlow::ConfigSig {
20+
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NewArrayExpr }
21+
22+
predicate isSink(DataFlow::Node sink) {
23+
exists(DeleteArrayExpr dae | dae.getExpr() = sink.asExpr())
24+
}
25+
}
26+
27+
module AllocationToDeleteFlow = DataFlow::Global<AllocationToDeleteConfig>;
28+
29+
module PathGraph = AllocationToDeleteFlow::PathGraph;
30+
31+
query predicate problems(
32+
Expr deleteExpr, AllocationToDeleteFlow::PathNode source, AllocationToDeleteFlow::PathNode sink,
33+
string message
34+
) {
35+
exists(NewArrayExpr newArray, DeleteArrayExpr deleteArray |
36+
not isExcluded(deleteArray.getExpr(), Config::getQuery()) and
37+
AllocationToDeleteFlow::flowPath(source, sink) and
38+
newArray = source.getNode().asExpr() and
39+
deleteArray.getExpr() = sink.getNode().asExpr() and
40+
not newArray.getType().getUnspecifiedType() =
41+
deleteArray.getExpr().getType().getUnspecifiedType() and
42+
deleteExpr = sink.getNode().asExpr() and
43+
message =
44+
"Array of type " + newArray.getType() + " is deleted through a pointer of type " +
45+
deleteArray.getExpr().getType() + "."
46+
)
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
problems
2+
| test.cpp:9:12:9:13 | l1 | test.cpp:6:19:6:37 | new[] | test.cpp:9:12:9:13 | l1 | Array of type DerivedClass * is deleted through a pointer of type BaseClass *. |
3+
edges
4+
| test.cpp:6:19:6:37 | new[] | test.cpp:9:12:9:13 | l1 | provenance | |
5+
| test.cpp:7:22:7:40 | new[] | test.cpp:10:12:10:13 | l2 | provenance | |
6+
nodes
7+
| test.cpp:6:19:6:37 | new[] | semmle.label | new[] |
8+
| test.cpp:7:22:7:40 | new[] | semmle.label | new[] |
9+
| test.cpp:9:12:9:13 | l1 | semmle.label | l1 |
10+
| test.cpp:10:12:10:13 | l2 | semmle.label | l2 |
11+
subpaths
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.donotdeleteanarraythroughapointeroftheincorrecttypeshared.DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared
3+
4+
module TestFileConfig implements DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeSharedConfigSig {
5+
Query getQuery() { result instanceof TestQuery }
6+
}
7+
8+
module Shared = DoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeShared<TestFileConfig>;
9+
10+
import Shared::PathGraph
11+
import Shared

cpp/cert/test/rules/EXP51-CPP/test.cpp renamed to cpp/common/test/rules/donotdeleteanarraythroughapointeroftheincorrecttypeshared/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ void test() {
88

99
delete[] l1; // NON_COMPLIANT - pointer to base class
1010
delete[] l2; // COMPLIANT - pointer to derived class
11-
}
11+
}

0 commit comments

Comments
 (0)