-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathNoNonFinalInConstructor.ql
More file actions
63 lines (57 loc) · 2.18 KB
/
NoNonFinalInConstructor.ql
File metadata and controls
63 lines (57 loc) · 2.18 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
/**
* @name Non-final method invocation in constructor
* @description If a constructor calls a method that is overridden in a subclass, the result can be
* unpredictable.
* @kind problem
* @problem.severity error
* @precision very-high
* @id java/non-final-call-in-constructor
* @tags quality
* reliability
* correctness
* logic
*/
import java
private predicate writtenInOneCallable(Field f) { strictcount(Callable m | m.writes(f)) = 1 }
private FieldWrite fieldWriteOnlyIn(Callable m, Field f) {
result.getField() = f and
m.writes(f) and
writtenInOneCallable(f)
}
private FieldRead nonFinalFieldRead(Callable m, Field f) {
result.getField() = f and
result.getEnclosingCallable() = m and
not f.isFinal()
}
private MethodCall unqualifiedCallToNonAbstractMethod(Constructor c, Method m) {
result.getEnclosingCallable() = c and
(
not exists(result.getQualifier()) or
result.getQualifier().(ThisAccess).getType() = c.getDeclaringType()
) and
m = result.getMethod() and
not m.isAbstract()
}
from
Constructor c, MethodCall ma, Method m, Method n, Field f, FieldRead fa, Constructor d,
FieldWrite fw
where
// Method access in a constructor
// which is an access to the object being initialized, ...
ma = unqualifiedCallToNonAbstractMethod(c, m) and
// ... there exists an overriding method in a subtype,
n.overrides+(m) and
n.getDeclaringType().getAStrictAncestor() = c.getDeclaringType() and
// ... the method is in a supertype of c,
m.getDeclaringType() = c.getDeclaringType().getAnAncestor() and
// ... `n` reads a non-final field `f`,
fa = nonFinalFieldRead(n, f) and
// ... which is declared in a subtype of `c`,
f.getDeclaringType().getAStrictAncestor() = c.getDeclaringType() and
// ... `f` is written only in the subtype constructor, and
fw = fieldWriteOnlyIn(d, f) and
// ... the subtype constructor calls (possibly indirectly) the offending super constructor.
d.callsConstructor+(c)
select ma, "One $@ $@ a $@ that is only $@ in the $@, so it is uninitialized in this $@.", n,
"overriding implementation", fa, "reads", f, "subclass field", fw, "initialized", d,
"subclass constructor", c, "super constructor"