Skip to content

Commit 5cbfdd1

Browse files
committed
C++: Cover more cases of returning *this
1 parent d144f0d commit 5cbfdd1

File tree

3 files changed

+18
-14
lines changed

3 files changed

+18
-14
lines changed

cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ predicate pointerThis(Expr e) {
2525
// `f(...)`
2626
// (includes `this = ...`, where `=` is overloaded so a `FunctionCall`)
2727
exists(FunctionCall fc | fc = e and callOnThis(fc) |
28-
exists(fc.getTarget().getBlock()) implies returnsPointerThis(fc.getTarget())
28+
returnsPointerThis(fc.getTarget())
2929
) or
3030

3131
// `this = ...` (where `=` is not overloaded, so an `AssignExpr`)
@@ -38,22 +38,33 @@ predicate dereferenceThis(Expr e) {
3838
// `f(...)`
3939
// (includes `*this = ...`, where `=` is overloaded so a `FunctionCall`)
4040
exists(FunctionCall fc | fc = e and callOnThis(fc) |
41-
exists(fc.getTarget().getBlock()) implies returnsDereferenceThis(fc.getTarget())
41+
returnsDereferenceThis(fc.getTarget())
4242
) or
4343

4444
// `*this = ...` (where `=` is not overloaded, so an `AssignExpr`)
4545
dereferenceThis(e.(AssignExpr).getLValue())
4646
}
4747

48+
/**
49+
* Holds if all `return` statements in `f` return `this`, possibly indirectly.
50+
* This includes functions whose body is not in the database.
51+
*/
4852
predicate returnsPointerThis(Function f) {
49-
forex(ReturnStmt s | s.getEnclosingFunction() = f |
53+
f.getType().getUnspecifiedType() instanceof PointerType and
54+
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
5055
// `return this`
5156
pointerThis(s.getExpr())
5257
)
5358
}
5459

60+
/**
61+
* Holds if all `return` statements in `f` return a reference to `*this`,
62+
* possibly indirectly. This includes functions whose body is not in the
63+
* database.
64+
*/
5565
predicate returnsDereferenceThis(Function f) {
56-
forex(ReturnStmt s | s.getEnclosingFunction() = f |
66+
f.getType().getUnspecifiedType() instanceof ReferenceType and
67+
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
5768
// `return *this`
5869
dereferenceThis(s.getExpr())
5970
)
@@ -72,10 +83,6 @@ predicate assignOperatorWithWrongType(Operator op, string msg) {
7283
predicate assignOperatorWithWrongResult(Operator op, string msg) {
7384
op.hasName("operator=")
7485
and not returnsDereferenceThis(op)
75-
// If a function does not have a reachable `ReturnStmt` then either its body
76-
// was not in the snapshot or it was established by the extractor or the CFG
77-
// pruning that the function never returns.
78-
and exists(ReturnStmt ret | ret.getEnclosingFunction() = op and reachable(ret))
7986
and not op.getType() instanceof VoidType
8087
and not assignOperatorWithWrongType(op, _)
8188
and msg = "Assignment operator in class " + op.getDeclaringType().getName() + " does not return a reference to *this."

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 82/AV Rule 82.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class AlwaysThrows {
134134
};
135135

136136
class Reachability {
137-
Reachability &operator=(Reachability &that) { // GOOD [FALSE POSITIVE]
137+
Reachability &operator=(Reachability &that) { // GOOD
138138
int one = 1;
139139
if (one)
140140
return *this;
@@ -160,11 +160,11 @@ class Reachability {
160160
return &staticInstance; // unreachable
161161
}
162162

163-
Reachability &operator=(int _val) { // GOOD [FALSE POSITIVE]
163+
Reachability &operator=(int _val) { // GOOD
164164
return returnThisReference();
165165
}
166166

167-
Reachability &operator=(short _val) { // GOOD [FALSE POSITIVE]
167+
Reachability &operator=(short _val) { // GOOD
168168
return *returnThisPointer();
169169
}
170170

cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 82/AV Rule 82.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,3 @@
22
| AV Rule 82.cpp:24:8:24:16 | operator= | Assignment operator in class Bad2 should have return type Bad2&. Otherwise a copy is created at each call. |
33
| AV Rule 82.cpp:63:29:63:37 | operator= | Assignment operator in class TemplateReturnAssignment<T> does not return a reference to *this. |
44
| AV Rule 82.cpp:63:29:63:37 | operator= | Assignment operator in class TemplateReturnAssignment<int> does not return a reference to *this. |
5-
| AV Rule 82.cpp:137:17:137:25 | operator= | Assignment operator in class Reachability does not return a reference to *this. |
6-
| AV Rule 82.cpp:163:17:163:25 | operator= | Assignment operator in class Reachability does not return a reference to *this. |
7-
| AV Rule 82.cpp:167:17:167:25 | operator= | Assignment operator in class Reachability does not return a reference to *this. |

0 commit comments

Comments
 (0)