-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathNonAssignedFields.ql
More file actions
90 lines (84 loc) · 3.23 KB
/
NonAssignedFields.ql
File metadata and controls
90 lines (84 loc) · 3.23 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* @name Field is never assigned a non-null value
* @description A field that is never assigned a value (except possibly 'null') just returns the
* default value when it is read.
* @kind problem
* @problem.severity warning
* @precision low
* @id java/unassigned-field
* @tags reliability
* maintainability
* useless-code
* external/cwe/cwe-457
*/
import java
import semmle.code.java.Reflection
/**
* Holds if `c` is of the form `Class<T>`, where `t` represents `T`.
*/
predicate isClassOf(ParameterizedClass c, RefType t) {
c.getGenericType() instanceof TypeClass and
c.getATypeArgument().getSourceDeclaration() = t.getSourceDeclaration()
}
/**
* Holds if field `f` is potentially accessed by an `AtomicReferenceFieldUpdater`.
*/
predicate subjectToAtomicReferenceFieldUpdater(Field f) {
exists(Class arfu, Method newUpdater, MethodAccess c |
arfu.hasQualifiedName("java.util.concurrent.atomic", "AtomicReferenceFieldUpdater") and
newUpdater = arfu.getAMethod() and
newUpdater.hasName("newUpdater") and
c.getMethod().getSourceDeclaration() = newUpdater and
isClassOf(c.getArgument(0).getType(), f.getDeclaringType()) and
isClassOf(c.getArgument(1).getType(), f.getType()) and
c.getArgument(2).(StringLiteral).getRepresentedString() = f.getName()
)
}
/**
* Holds if `f` is ever looked up reflectively.
*/
predicate lookedUpReflectively(Field f) {
exists(MethodAccess getDeclaredField |
isClassOf(getDeclaredField.getQualifier().getType(), f.getDeclaringType()) and
getDeclaredField.getMethod().hasName("getDeclaredField") and
getDeclaredField.getArgument(0).(StringLiteral).getRepresentedString() = f.getName()
)
}
/**
* Holds if `rt` registers a VM observer in its static initialiser.
*/
predicate isVMObserver(RefType rt) {
exists(Method register |
register.getDeclaringType().hasQualifiedName("sun.jvm.hotspot.runtime", "VM") and
register.hasName("registerVMInitializedObserver") and
register.getAReference().getEnclosingCallable().(StaticInitializer).getDeclaringType() = rt
)
}
from Field f, FieldRead fr
where
f.fromSource() and
fr.getField().getSourceDeclaration() = f and
not f.getDeclaringType() instanceof EnumType and
forall(Assignment ae, Field g | ae.getDest() = g.getAnAccess() and g.getSourceDeclaration() = f |
ae.getSource() instanceof NullLiteral
) and
not exists(UnaryAssignExpr ua, Field g |
ua.getExpr() = g.getAnAccess() and
g.getSourceDeclaration() = f
) and
not f.isFinal() and
// Exclude fields that may be accessed reflectively.
not reflectivelyWritten(f) and
not lookedUpReflectively(f) and
not subjectToAtomicReferenceFieldUpdater(f) and
// If an object containing `f` is, or may be, passed to a native method,
// assume it initializes the field.
not exists(Callable c | c.isNative() |
c.getAParameter().getType() = f.getDeclaringType() or
c.getAReference().getAnArgument().getType() = f.getDeclaringType() or
c.getDeclaringType() = f.getDeclaringType()
) and
// Exclude special VM classes.
not isVMObserver(f.getDeclaringType())
select f, "Field " + f.getName() + " never assigned non-null value, yet it is read at $@.", fr,
fr.getFile().getStem() + ".java:" + fr.getLocation().getStartLine()