forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInconsistentCompareTo.ql
More file actions
54 lines (50 loc) · 1.99 KB
/
InconsistentCompareTo.ql
File metadata and controls
54 lines (50 loc) · 1.99 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
/**
* @name Inconsistent compareTo
* @description If a class overrides 'compareTo' but not 'equals', it may mean that 'compareTo'
* and 'equals' are inconsistent.
* @kind problem
* @problem.severity warning
* @precision medium
* @id java/inconsistent-compareto-and-equals
* @suites security-and-quality
* @tags reliability
* correctness
*/
import java
import semmle.code.java.frameworks.Lombok
/** Holds if `t` implements `Comparable` on `typeArg`. */
predicate implementsComparableOn(RefType t, RefType typeArg) {
exists(RefType cmp |
t.getAnAncestor() = cmp and
cmp.getSourceDeclaration().hasQualifiedName("java.lang", "Comparable")
|
// Either `t` extends `Comparable<T>`, in which case `typeArg` is `T`, ...
typeArg = cmp.(ParameterizedType).getATypeArgument() and not typeArg instanceof Wildcard
or
// ... or it extends the raw type `Comparable`, in which case `typeArg` is `Object`.
cmp instanceof RawType and typeArg instanceof TypeObject
)
}
class CompareToMethod extends Method {
CompareToMethod() {
this.hasName("compareTo") and
this.isPublic() and
this.getNumberOfParameters() = 1 and
// To implement `Comparable<T>.compareTo`, the parameter must either have type `T` or `Object`.
exists(RefType typeArg, Type firstParamType |
implementsComparableOn(this.getDeclaringType(), typeArg) and
firstParamType = this.getParameter(0).getType() and
(firstParamType = typeArg or firstParamType instanceof TypeObject)
)
}
}
from Class c, CompareToMethod compareToMethod
where
c.fromSource() and
compareToMethod.fromSource() and
not exists(EqualsMethod em | em.getDeclaringType().getSourceDeclaration() = c) and
compareToMethod.getDeclaringType().getSourceDeclaration() = c and
// Exclude classes annotated with relevant Lombok annotations.
not c instanceof LombokEqualsAndHashCodeGeneratedClass
select c, "This class declares $@ but inherits equals; the two could be inconsistent.",
compareToMethod, "compareTo"