Skip to content

Commit 298f70f

Browse files
authored
Merge pull request github#6120 from MathiasVP/not-overflow-is-barrier-in-cwe-190
C++: Recognize any non-overflowing arithmetic expression as a barrier for `cpp/uncontrolled-arithmetic`
2 parents c096461 + a611e76 commit 298f70f

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ predicate boundedDiv(Expr e, Expr left) { e = left }
3636

3737
/**
3838
* An operand `e` of a remainder expression `rem` (i.e., `rem` is either a `RemExpr` or
39-
* an `AssignRemExpr`) with left-hand side `left` and right-ahnd side `right` is bounded
39+
* an `AssignRemExpr`) with left-hand side `left` and right-hand side `right` is bounded
4040
* when `e` is `left` and `right` is upper bounded by some number that is less than the maximum integer
4141
* allowed by the result type of `rem`.
4242
*/
@@ -59,10 +59,17 @@ predicate boundedBitwiseAnd(Expr e, Expr andExpr, Expr operand1, Expr operand2)
5959
}
6060

6161
/**
62-
* Holds if `fc` is a part of the left operand of a binary operation that greatly reduces the range
63-
* of possible values.
62+
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operand of an
63+
* operation that may greatly reduces the range of possible values.
6464
*/
6565
predicate bounded(Expr e) {
66+
(
67+
e instanceof UnaryArithmeticOperation or
68+
e instanceof BinaryArithmeticOperation or
69+
e instanceof AssignArithmeticOperation
70+
) and
71+
not convertedExprMightOverflow(e)
72+
or
6673
// For `%` and `&` we require that `e` is bounded by a value that is strictly smaller than the
6774
// maximum possible value of the result type of the operation.
6875
// For example, the function call `rand()` is considered bounded in the following program:
@@ -85,7 +92,7 @@ predicate bounded(Expr e) {
8592
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
8693
)
8794
or
88-
// Optimitically assume that a division always yields a much smaller value.
95+
// Optimitically assume that a division or right shift always yields a much smaller value.
8996
boundedDiv(e, any(DivExpr div).getLeftOperand())
9097
or
9198
boundedDiv(e, any(AssignDivExpr div).getLValue())

cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
int rand(void);
55
void trySlice(int start, int end);
6+
void add_100(int);
67

78
#define RAND() rand()
89
#define RANDN(n) (rand() % n)
910
#define RAND2() (rand() ^ rand())
10-
11-
11+
#define RAND_MAX 32767
1212

1313

1414

@@ -99,4 +99,14 @@ void randomTester() {
9999
*ptr_r = RAND();
100100
r -= 100; // BAD
101101
}
102+
103+
{
104+
int r = rand();
105+
r = ((2.0 / (RAND_MAX + 1)) * r - 1.0);
106+
add_100(r);
107+
}
102108
}
109+
110+
void add_100(int r) {
111+
r += 100; // GOOD
112+
}

0 commit comments

Comments
 (0)