-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathNoComparisonOnFloats.ql
More file actions
70 lines (63 loc) · 1.87 KB
/
NoComparisonOnFloats.ql
File metadata and controls
70 lines (63 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* @name Equality test on floating point values
* @description Equality tests on floating point values may lead to unexpected results.
* @kind problem
* @problem.severity warning
* @precision low
* @id java/equality-test-on-floating-point
* @tags reliability
* correctness
*/
import semmle.code.java.Type
import semmle.code.java.Expr
// Either `float`, `double`, `Float`, or `Double`.
class Floating extends Type {
Floating() {
exists(string s | s = this.getName().toLowerCase() |
s = "float" or
s = "double"
)
}
}
predicate trivialLiteral(Literal e) {
e.getValue() = "0.0" or
e.getValue() = "0" or
e.getValue() = "1.0" or
e.getValue() = "1"
}
predicate definedConstant(Expr e) {
exists(Field f |
f.isStatic() and
(
f.getDeclaringType().hasName("Float") or
f.getDeclaringType().hasName("Double")
)
|
e = f.getAnAccess()
)
}
// The contract of `compareTo` would not really allow anything other than `<` or `>` on floats.
predicate comparisonMethod(Method m) { m.getName() = "compareTo" }
// Check for equalities of the form `a.x == b.x` or `a.x == x`, where `x` is assigned to `a.x`,
// which are less interesting but occur often.
predicate similarVarComparison(EqualityTest e) {
exists(Field f |
e.getLeftOperand() = f.getAnAccess() and
e.getRightOperand() = f.getAnAccess()
)
or
exists(Field f, Variable v |
e.getAnOperand() = f.getAnAccess() and
e.getAnOperand() = v.getAnAccess() and
f.getAnAssignedValue() = v.getAnAccess()
)
}
from EqualityTest ee
where
ee.getAnOperand().getType() instanceof Floating and
not ee.getAnOperand() instanceof NullLiteral and
not trivialLiteral(ee.getAnOperand()) and
not definedConstant(ee.getAnOperand()) and
not similarVarComparison(ee) and
not comparisonMethod(ee.getEnclosingCallable())
select ee, "Equality test on floating point values."