Skip to content

Commit 940134a

Browse files
committed
Add incorrect-rounding-division.ql
1 parent 102663e commit 940134a

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

codeql-custom-queries-java/not-working-queries/redundant-value-or-type-check.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ private predicate accessSameField(FieldAccess a, FieldAccess b) {
1919
or accessSameVariable(a.getQualifier(), b.getQualifier())
2020
}
2121

22-
// TODO: Already declared in other queries, reduce code duplication
22+
// TODO: Use `accessSameVarOfSameOwner` from VarAccess?
2323
predicate accessSameVariable(VarAccess a, VarAccess b) {
2424
exists (Variable var | var = a.getVariable() |
2525
var = b.getVariable()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Finds expressions which seem to try rounding down a value `a` to the next smaller
3+
* multiple of `b`, but which seem to be incorrectly implemented.
4+
*
5+
* The correct expression is `a / b * b` (where `a` and `b` are integral numbers).
6+
* The following incorrect expressions are detected:
7+
* - `a / b` producing a floating point number; in that case `a / b * b` is most
8+
* likely the same as `a` (except for some floating point precision loss),
9+
* or possibly brackets are missing and it should have been `a / (b * b)`
10+
* - `a / b * a`; the `* a` seems incorrect and should probably be `* b`
11+
*
12+
* @id todo
13+
* @kind problem
14+
*/
15+
16+
import java
17+
import lib.VarAccess
18+
19+
predicate haveSameValue(Expr a, Expr b) {
20+
a.getType() = b.getType() and a.(Literal).getValue() = b.(Literal).getValue()
21+
or
22+
accessSameVarOfSameOwner(a, b)
23+
}
24+
25+
from DivExpr div, Expr divisor, MulExpr mul, Expr mulOperand
26+
where
27+
// Match `... / divisor * mulOperand`
28+
mul.getLeftOperand() = div and
29+
mulOperand = mul.getRightOperand() and
30+
div.getRightOperand() = divisor and
31+
(
32+
// Redundant division because result is floating point, e.g. `(a / 2.0) * 2` (= `a`, with some floating point precision loss)
33+
div.getType() instanceof FloatingPointType and
34+
haveSameValue(divisor, mulOperand)
35+
or
36+
// TODO: Maybe remove this case (also from documentation of query)? At least Variant Analysis did not find any case of this
37+
38+
// Or accidental `(a / b) * a` when it should probably have been `(a / b) * b`
39+
haveSameValue(div.getLeftOperand(), mulOperand) and
40+
// Ignore if this calculates square of expression, e.g. `a / b * a / b`
41+
not exists(DivExpr rightDiv |
42+
rightDiv.getLeftOperand() = mul and
43+
haveSameValue(rightDiv.getRightOperand(), divisor)
44+
)
45+
)
46+
select mul, "Performs incorrect rounding division"

codeql-custom-queries-java/queries/likely-bugs/pointless-binary-operation.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import java
1414
import lib.Literals
1515
import lib.Operations
1616

17+
// TODO: Also cover assign-op, e.g. `x += 0`
18+
// TODO: Also cover bitwise operations, e.g. `| 0`, `| -1`, `& 0` `& -1`
19+
// (don't have to check if literal is `int` or `long`; e.g. `-1` is implicitly converted to `-1L`)
20+
1721
abstract class PointlessOperation extends Expr {
1822
abstract string getDescription();
1923
}

0 commit comments

Comments
 (0)