Skip to content

Commit df73bb3

Browse files
committed
CPP: Fix performance issue. Also has a small positive effect on correctness.
1 parent f0085ed commit df73bb3

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

cpp/ql/src/Critical/NewDelete.qll

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ predicate allocExprOrIndirect(Expr alloc, string kind) {
4646
alloc.(FunctionCall).getTarget() = rtn.getEnclosingFunction() and
4747
(
4848
allocExprOrIndirect(rtn.getExpr(), kind) or
49-
allocReaches(rtn.getExpr(), _, kind)
49+
allocReaches0(rtn.getExpr(), _, kind)
5050
)
5151
)
5252
}
5353

5454
/**
55-
* Holds if `v` is assigned value `e`, and `e` is not known to be `0`.
55+
* Holds if `v` is a global variable assigned value `e`, and `e` is not known
56+
* to be `0`.
5657
*/
5758
private predicate nonNullGlobalAssignment(Variable v, Expr e) {
5859
not v instanceof LocalScopeVariable and
@@ -61,17 +62,13 @@ private predicate nonNullGlobalAssignment(Variable v, Expr e) {
6162
}
6263

6364
/**
64-
* Holds if `v` is a non-local variable which is assigned only with allocations of
65-
* type `kind` (it may also be assigned with NULL).
65+
* Holds if `v` is a non-local variable which is assigned with allocations of
66+
* type `kind`.
6667
*/
67-
private predicate allocReachesVariable(Variable v, Expr alloc, string kind) {
68+
private cached predicate allocReachesVariable(Variable v, Expr alloc, string kind) {
6869
exists(Expr mid |
6970
nonNullGlobalAssignment(v, mid) and
70-
allocReaches(mid, alloc, kind)
71-
) and
72-
forall(Expr mid |
73-
nonNullGlobalAssignment(v, mid) |
74-
allocReaches(mid, _, kind)
71+
allocReaches0(mid, alloc, kind)
7572
)
7673
}
7774

@@ -80,22 +77,35 @@ private predicate allocReachesVariable(Variable v, Expr alloc, string kind) {
8077
* result of a previous memory allocation `alloc`. `kind` is a
8178
* string describing the type of that allocation.
8279
*/
83-
predicate allocReaches(Expr e, Expr alloc, string kind) {
80+
private predicate allocReaches0(Expr e, Expr alloc, string kind) {
8481
(
8582
// alloc
8683
allocExprOrIndirect(alloc, kind) and
8784
e = alloc
8885
) or exists(SsaDefinition def, LocalScopeVariable v |
8986
// alloc via SSA
90-
allocReaches(def.getAnUltimateDefiningValue(v), alloc, kind) and
87+
allocReaches0(def.getAnUltimateDefiningValue(v), alloc, kind) and
9188
e = def.getAUse(v)
9289
) or exists(Variable v |
93-
// alloc via a singly assigned global
90+
// alloc via a global
9491
allocReachesVariable(v, alloc, kind) and
9592
e.(VariableAccess).getTarget() = v
9693
)
9794
}
9895

96+
/**
97+
* Holds if `e` is an expression which may evaluate to the
98+
* result of previous memory allocations `alloc` only of type
99+
* `kind`.
100+
*/
101+
predicate allocReaches(Expr e, Expr alloc, string kind) {
102+
allocReaches0(e, alloc, kind) and
103+
not exists(string k2 |
104+
allocReaches0(e, _, k2) and
105+
kind != k2
106+
)
107+
}
108+
99109
/**
100110
* Holds if `free` is a use of free or delete. `freed` is the
101111
* expression that is freed / deleted and `kind` is a string

cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,3 @@
1212
| test.cpp:235:2:235:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:227:7:227:13 | new | new |
1313
| test.cpp:239:2:239:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:228:7:228:17 | new[] | new[] |
1414
| test.cpp:272:3:272:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:265:7:265:13 | new | new |
15-
| test.cpp:367:3:367:10 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:359:14:359:19 | call to malloc | malloc |
16-
| test.cpp:370:3:370:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:356:7:356:15 | new | new |

cpp/ql/test/query-tests/Critical/NewFree/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,10 @@ void test12(bool cond)
364364

365365
if (cond)
366366
{
367-
delete y; // GOOD [FALSE POSITIVE]
367+
delete y; // GOOD
368368
delete z; // GOOD
369369
} else {
370-
free(y); // GOOD [FALSE POSITIVE]
370+
free(y); // GOOD
371371
free(z); // GOOD
372372
}
373373
}

0 commit comments

Comments
 (0)