Skip to content

Commit 691a316

Browse files
committed
C++: Add tests to cpp/unsigned-difference-expression-compared-zero and remove a couple of classes of FPs.
1 parent 50f2557 commit 691a316

File tree

4 files changed

+106
-1
lines changed

4 files changed

+106
-1
lines changed

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,28 @@
1313

1414
import cpp
1515
import semmle.code.cpp.commons.Exclusions
16+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
17+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
18+
import semmle.code.cpp.controlflow.Guards
19+
20+
/** Holds if `sub` will never be nonnegative. */
21+
predicate nonNegative(SubExpr sub) {
22+
not exprMightOverflowNegatively(sub.getFullyConverted())
23+
or
24+
// The subtraction is guarded by a check of the form `left >= right`.
25+
exists(GuardCondition guard, Expr left, Expr right |
26+
left = globalValueNumber(sub.getLeftOperand()).getAnExpr() and
27+
right = globalValueNumber(sub.getRightOperand()).getAnExpr() and
28+
guard.controls(sub.getBasicBlock(), true) and
29+
guard.ensuresLt(left, right, 0, sub.getBasicBlock(), false)
30+
)
31+
}
1632

1733
from RelationalOperation ro, SubExpr sub
1834
where
1935
not isFromMacroDefinition(ro) and
2036
ro.getLesserOperand().getValue().toInt() = 0 and
2137
ro.getGreaterOperand() = sub and
22-
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned()
38+
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
39+
not nonNegative(sub)
2340
select ro, "Difference in condition is always greater than or equal to zero"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| test.cpp:6:5:6:13 | ... > ... | Difference in condition is always greater than or equal to zero |
2+
| test.cpp:10:8:10:24 | ... > ... | Difference in condition is always greater than or equal to zero |
3+
| test.cpp:15:9:15:25 | ... > ... | Difference in condition is always greater than or equal to zero |
4+
| test.cpp:32:12:32:20 | ... > ... | Difference in condition is always greater than or equal to zero |
5+
| test.cpp:39:12:39:20 | ... > ... | Difference in condition is always greater than or equal to zero |
6+
| test.cpp:47:5:47:13 | ... > ... | Difference in condition is always greater than or equal to zero |
7+
| test.cpp:55:5:55:13 | ... > ... | Difference in condition is always greater than or equal to zero |
8+
| test.cpp:62:5:62:13 | ... > ... | Difference in condition is always greater than or equal to zero |
9+
| test.cpp:69:5:69:13 | ... > ... | Difference in condition is always greater than or equal to zero |
10+
| test.cpp:75:8:75:16 | ... > ... | Difference in condition is always greater than or equal to zero |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
int getAnInt();
2+
3+
bool cond();
4+
5+
void test(unsigned x, unsigned y, bool unknown) {
6+
if(x - y > 0) { } // BAD
7+
8+
unsigned total = getAnInt();
9+
unsigned limit = getAnInt();
10+
while(limit - total > 0) { // BAD
11+
total += getAnInt();
12+
}
13+
14+
if(total <= limit) {
15+
while(limit - total > 0) { // GOOD [FALSE POSITIVE]
16+
total += getAnInt();
17+
if(total > limit) break;
18+
}
19+
}
20+
21+
if(x >= y) {
22+
bool b = x - y > 0; // GOOD
23+
}
24+
25+
if((int)(x - y) >= 0) { } // GOOD. Maybe an overflow happened, but the result is converted to the "likely intended" result before the comparison
26+
27+
if(unknown) {
28+
y = x & 0xFF;
29+
} else {
30+
y = x;
31+
}
32+
bool b1 = x - y > 0; // GOOD [FALSE POSITIVE]
33+
34+
x = getAnInt();
35+
y = getAnInt();
36+
if(y > x) {
37+
y = x - 1;
38+
}
39+
bool b2 = x - y > 0; // GOOD [FALSE POSITIVE]
40+
41+
int N = getAnInt();
42+
y = x;
43+
while(cond()) {
44+
if(unknown) { y--; }
45+
}
46+
47+
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
48+
49+
x = y;
50+
while(cond()) {
51+
if(unknown) break;
52+
y--;
53+
}
54+
55+
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
56+
57+
y = 0;
58+
for(int i = 0; i < x; ++i) {
59+
if(unknown) { ++y; }
60+
}
61+
62+
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
63+
64+
x = y;
65+
while(cond()) {
66+
if(unknown) { x++; }
67+
}
68+
69+
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
70+
71+
int n = getAnInt();
72+
if (n > x - y) { n = x - y; }
73+
if (n > 0) {
74+
y += n; // NOTE: `n` is at most `x - y` at this point.
75+
if (x - y > 0) {} // GOOD [FALSE POSITIVE]
76+
}
77+
}

0 commit comments

Comments
 (0)