Skip to content

Commit 48ff8e2

Browse files
committed
C++: Rewrite the range analysis exclusion to be recursive and more robust.
1 parent 3ecd135 commit 48ff8e2

File tree

3 files changed

+22
-19
lines changed

3 files changed

+22
-19
lines changed

cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,22 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
2929
)
3030
}
3131

32-
/** Holds if `sub` will never be negative. */
33-
predicate nonNegative(SubExpr sub) {
34-
not exprMightOverflowNegatively(sub.getFullyConverted())
32+
/**
33+
* Holds if `e` is known to be less than or equal to `sub.getLeftOperand()`.
34+
*/
35+
predicate exprIsSubLeftOrLess(SubExpr sub, Expr e) {
36+
e = sub.getLeftOperand()
37+
or
38+
exists(Expr other |
39+
// GVN equality
40+
exprIsSubLeftOrLess(sub, other) and
41+
globalValueNumber(e) = globalValueNumber(other)
42+
)
3543
or
36-
// The subtraction is guarded by a check of the form `left >= right`.
37-
exists(GVN left, GVN right |
38-
// This is basically a poor man's version of a directional unbind operator.
39-
strictcount([left, globalValueNumber(sub.getLeftOperand())]) = 1 and
40-
strictcount([right, globalValueNumber(sub.getRightOperand())]) = 1 and
41-
isGuarded(sub, left.getAnExpr(), right.getAnExpr())
44+
exists(Expr other |
45+
// guard constraining `sub`
46+
exprIsSubLeftOrLess(sub, other) and
47+
isGuarded(sub, other, e) // left >= right
4248
)
4349
}
4450

@@ -49,5 +55,5 @@ where
4955
ro.getLesserOperand().getValue().toInt() = 0 and
5056
ro.getGreaterOperand() = sub and
5157
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
52-
not nonNegative(sub)
58+
not exprIsSubLeftOrLess(sub, sub.getRightOperand())
5359
select ro, "Unsigned subtraction can never be negative."

cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/UnsignedDifferenceExpressionComparedZero.expected

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
| test.cpp:62:5:62:13 | ... > ... | Unsigned subtraction can never be negative. |
99
| test.cpp:69:5:69:13 | ... > ... | Unsigned subtraction can never be negative. |
1010
| test.cpp:75:8:75:16 | ... > ... | Unsigned subtraction can never be negative. |
11-
| test.cpp:83:6:83:14 | ... > ... | Unsigned subtraction can never be negative. |
1211
| test.cpp:92:6:92:14 | ... > ... | Unsigned subtraction can never be negative. |
1312
| test.cpp:101:6:101:14 | ... > ... | Unsigned subtraction can never be negative. |
14-
| test.cpp:110:6:110:14 | ... > ... | Unsigned subtraction can never be negative. |
1513
| test.cpp:119:6:119:14 | ... > ... | Unsigned subtraction can never be negative. |
1614
| test.cpp:128:6:128:14 | ... > ... | Unsigned subtraction can never be negative. |
1715
| test.cpp:137:6:137:14 | ... > ... | Unsigned subtraction can never be negative. |
@@ -20,7 +18,6 @@
2018
| test.cpp:182:6:182:14 | ... > ... | Unsigned subtraction can never be negative. |
2119
| test.cpp:195:6:195:14 | ... > ... | Unsigned subtraction can never be negative. |
2220
| test.cpp:208:6:208:14 | ... > ... | Unsigned subtraction can never be negative. |
23-
| test.cpp:219:7:219:15 | ... > ... | Unsigned subtraction can never be negative. |
24-
| test.cpp:226:8:226:16 | ... > ... | Unsigned subtraction can never be negative. |
21+
| test.cpp:241:10:241:18 | ... > ... | Unsigned subtraction can never be negative. |
2522
| test.cpp:252:10:252:18 | ... > ... | Unsigned subtraction can never be negative. |
2623
| test.cpp:266:10:266:24 | ... > ... | Unsigned subtraction can never be negative. |

cpp/ql/test/query-tests/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero/test.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void test2() {
8080
unsigned int a = getAnInt();
8181
unsigned int b = a;
8282

83-
if (a - b > 0) { // GOOD (as a = b) [FALSE POSITIVE]
83+
if (a - b > 0) { // GOOD (as a = b)
8484
// ...
8585
}
8686
}
@@ -107,7 +107,7 @@ void test5() {
107107
unsigned int b = getAnInt();
108108
unsigned int a = b;
109109

110-
if (a - b > 0) { // GOOD (as a = b) [FALSE POSITIVE]
110+
if (a - b > 0) { // GOOD (as a = b)
111111
// ...
112112
}
113113
}
@@ -216,14 +216,14 @@ void test12() {
216216
unsigned int c;
217217

218218
if ((b <= c) && (c <= a)) {
219-
if (a - b > 0) { // GOOD (as b <= a) [FALSE POSITIVE]
219+
if (a - b > 0) { // GOOD (as b <= a)
220220
// ...
221221
}
222222
}
223223

224224
if (b <= c) {
225225
if (c <= a) {
226-
if (a - b > 0) { // GOOD (as b <= a) [FALSE POSITIVE]
226+
if (a - b > 0) { // GOOD (as b <= a)
227227
// ...
228228
}
229229
}
@@ -238,7 +238,7 @@ int test13() {
238238
return 0;
239239
}
240240

241-
return (a - b > 0); // GOOD (as b = 0)
241+
return (a - b > 0); // GOOD (as b = 0) [FALSE POSITIVE]
242242
}
243243

244244
int test14() {

0 commit comments

Comments
 (0)