-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathNonAssignedFields.ql
More file actions
85 lines (79 loc) · 3.04 KB
/
NonAssignedFields.ql
File metadata and controls
85 lines (79 loc) · 3.04 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
/**
* @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, MethodCall 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).getValue() = f.getName()
)
}
/**
* Holds if `f` is ever looked up reflectively.
*/
predicate lookedUpReflectively(Field f) {
exists(MethodCall getDeclaredField |
isClassOf(getDeclaredField.getQualifier().getType(), f.getDeclaringType()) and
getDeclaredField.getMethod().hasName("getDeclaredField") and
getDeclaredField.getArgument(0).(StringLiteral).getValue() = 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() = f and
not f.getDeclaringType() instanceof EnumType and
forall(Assignment ae | ae.getDest() = f.getAnAccess() | ae.getSource() instanceof NullLiteral) and
not exists(UnaryAssignExpr ua | ua.getExpr() = f.getAnAccess()) 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, "The field '" + f.getName() + "' is never explicitly assigned a value, yet $@.", fr,
"the field is read"