Skip to content

Commit 7365b94

Browse files
committed
Add signed-rshift-on-loop-variable.ql
1 parent 594df79 commit 7365b94

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Finds loops which check whether an integral variable has the value `0` or whether
3+
* certain bits are set or cleared, and which uses a signed right shift `>>` in the
4+
* loop to update the variable. This can lead to an endless loop when the variable
5+
* can be negative because in that case the `>>` operator keeps adding a `1` bit on
6+
* the left and the loop condition might therefore always be true.
7+
*
8+
* @kind problem
9+
*/
10+
11+
import java
12+
13+
from LoopStmt loop, Expr check, Variable var, Expr shift
14+
where
15+
(
16+
// Checks for `!= 0`
17+
exists(NEExpr notZeroCheck | check = notZeroCheck |
18+
loop.getCondition() = notZeroCheck
19+
and (
20+
notZeroCheck.getAnOperand() = var.getAnAccess()
21+
or notZeroCheck.getAnOperand().(AssignRShiftExpr) = shift
22+
)
23+
and notZeroCheck.getAnOperand().(Literal).getValue() = "0"
24+
)
25+
// Or checks for `& x == 1` or `& x != 0`
26+
or exists(EqualityTest equalityCheck, AndBitwiseExpr bitAnd | check = equalityCheck |
27+
loop.getCondition() = equalityCheck
28+
and equalityCheck.getAnOperand() = bitAnd
29+
and if (equalityCheck.polarity() = true) then (
30+
equalityCheck.getAnOperand().(Literal).getValue() = "1"
31+
) else (
32+
equalityCheck.getAnOperand().(Literal).getValue() = "0"
33+
)
34+
and (
35+
bitAnd.getAnOperand() = var.getAnAccess()
36+
or bitAnd.getAnOperand().(AssignRShiftExpr) = shift
37+
)
38+
)
39+
)
40+
and shift.getAnEnclosingStmt() = loop
41+
and (
42+
// `x = x >> ...`
43+
exists(AssignExpr assign |
44+
assign.getDest() = var.getAnAccess()
45+
and assign.getRhs() = shift
46+
and shift.(RShiftExpr).getLeftOperand() = var.getAnAccess()
47+
and assign.getAnEnclosingStmt() = loop
48+
)
49+
// Or `x >>= ...`
50+
or shift.(AssignRShiftExpr).getDest() = var.getAnAccess()
51+
)
52+
select check, "Might result in endless loop due to $@", shift, "this signed right shift"

0 commit comments

Comments
 (0)