Skip to content

Commit 666f6cf

Browse files
committed
Add constant-expression-overflow.ql
1 parent 730cbfd commit 666f6cf

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Finds constant expressions which overflow. Most likely this is a bug and the
3+
* value should be of type `long` to avoid overflow.
4+
* For example:
5+
* ```java
6+
* long timeout = 1000 * 1000 * 1000 * 1000; // Overflows, actual value is: -727379968
7+
*
8+
* // Should instead convert one value to long (e.g. by adding `L`):
9+
* long timeout = 1000L * 1000 * 1000 * 1000;
10+
* ```
11+
*
12+
* @kind problem
13+
*/
14+
15+
// Currently only checks `int` constants but not `long` because CodeQL has no 64-bit integer type
16+
17+
import java
18+
19+
from BinaryExpr overflowingExpr
20+
where
21+
// Positive to negative (addition): +a + +b = -c
22+
(
23+
overflowingExpr instanceof AddExpr
24+
and overflowingExpr.getLeftOperand().(CompileTimeConstantExpr).getIntValue() > 0
25+
and overflowingExpr.getRightOperand().(CompileTimeConstantExpr).getIntValue() > 0
26+
and overflowingExpr.(CompileTimeConstantExpr).getIntValue() <= 0
27+
)
28+
// Negative to positive (addition): -a + -b = +c
29+
or (
30+
overflowingExpr instanceof AddExpr
31+
and overflowingExpr.getLeftOperand().(CompileTimeConstantExpr).getIntValue() < 0
32+
and overflowingExpr.getRightOperand().(CompileTimeConstantExpr).getIntValue() < 0
33+
and overflowingExpr.(CompileTimeConstantExpr).getIntValue() >= 0
34+
)
35+
// Negative to positive (subtraction): -a - +b = +c
36+
or (
37+
overflowingExpr instanceof SubExpr
38+
and overflowingExpr.getLeftOperand().(CompileTimeConstantExpr).getIntValue() < 0
39+
and overflowingExpr.getRightOperand().(CompileTimeConstantExpr).getIntValue() > 0
40+
and overflowingExpr.(CompileTimeConstantExpr).getIntValue() >= 0
41+
// Ignore expressions like `(1 << 31) - 1`
42+
and not overflowingExpr.getLeftOperand() instanceof LeftShiftExpr
43+
)
44+
// Multiplication overflow
45+
or exists(int left, int right |
46+
overflowingExpr instanceof MulExpr
47+
and left = overflowingExpr.getLeftOperand().(CompileTimeConstantExpr).getIntValue()
48+
and right = overflowingExpr.getRightOperand().(CompileTimeConstantExpr).getIntValue()
49+
and (
50+
left > 0 and right > 0 and right > 2147483647 / left
51+
or
52+
// Divide by positive value here and below to avoid overflow (e.g. -2147483648 / -1 overflows)
53+
left > 0 and right < 0 and right < -2147483648 / left
54+
or
55+
left < 0 and right > 0 and left < -2147483648 / right
56+
or
57+
// Checks 2147483647 because minus * minus = plus
58+
left < 0 and right < 0 and right < 2147483647 / left
59+
)
60+
)
61+
select overflowingExpr, "Value of this constant expression overflows"

0 commit comments

Comments
 (0)