-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathNonAssignedFields.ql
More file actions
123 lines (113 loc) · 3.7 KB
/
NonAssignedFields.ql
File metadata and controls
123 lines (113 loc) · 3.7 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* @name Field is never assigned a non-default value
* @description Fields are automatically initialised with the default values for their type, which may not be the intent: prefer explicit initialisation.
* @kind problem
* @problem.severity recommendation
* @precision low
* @id cs/unassigned-field
* @tags reliability
* maintainability
* useless-code
* external/cwe/cwe-457
*/
import csharp
import semmle.code.csharp.frameworks.System
import semmle.code.csharp.frameworks.system.runtime.InteropServices
// Any field transitively contained in t.
Field getANestedField(ValueOrRefType t)
{
result.getDeclaringType() = t
or
exists(Field mid |
mid=getANestedField(t)
and
mid.getType() = result.getDeclaringType())
}
// Any ValueOrRefType referenced by a Type, including TypeParameters.
ValueOrRefType getAReferencedType(Type t)
{
result = t
or
result = t.(TypeParameter).getASuppliedType()
}
predicate isTypeExternallyInitialized(ValueOrRefType t)
{
// The type got created via a call to PtrToStructure().
exists(MethodCall mc |
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod()
and
t = getAReferencedType(mc.getArgument(1).(TypeofExpr).getTypeAccess().getTarget())
)
// The type got created via a call to PtrToStructure().
or exists(MethodCall mc |
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod()
and
t = getAReferencedType(mc.getArgument(1).getType())
)
// An extern method exists which could initialize the type.
or exists(Method m, Parameter p |
isExternMethod(m) and
p=m.getAParameter() and
t = p.getType()
|
p.isOut() or p.isRef())
// The data structure has been cast to a pointer - all bets are off.
or exists(CastExpr c |
t = getAReferencedType(c.getTargetType().(PointerType).getReferentType()))
}
// The type is potentially marshaled using an extern or interop.
predicate isFieldExternallyInitialized(Field f)
{
exists(ValueOrRefType t |
f = getANestedField(t)
and
isTypeExternallyInitialized(t))
}
predicate isExternMethod(Method externMethod)
{
externMethod.isExtern()
or
externMethod.getAnAttribute().getType() instanceof SystemRuntimeInteropServicesDllImportAttributeClass
or
externMethod.getDeclaringType().getAnAttribute().getType() instanceof SystemRuntimeInteropServicesComImportAttributeClass
}
from Field f, FieldRead fa
where
f.fromSource()
and not extractionIsStandalone()
and not f.isReadOnly()
and not f.isConst()
and not f.getDeclaringType() instanceof Enum
and not f.getType() instanceof Struct
and not exists(Assignment ae, Field g |
ae.getLValue().(FieldAccess).getTarget() = g
and g.getSourceDeclaration() = f
and not (ae.getRValue() instanceof NullLiteral)
)
and not exists(MethodCall mc, int i, Field g |
exists(Parameter p | mc.getTarget().getParameter(i) = p |
p.isOut() or p.isRef()
)
and mc.getArgument(i) = g.getAnAccess()
and g.getSourceDeclaration() = f
)
and not isFieldExternallyInitialized(f)
and not exists(f.getAnAttribute())
and not exists(Expr init, Field g |
g.getSourceDeclaration() = f
and g.getInitializer() = init
and not init instanceof NullLiteral
)
and not exists(AssignOperation ua, Field g |
ua.getLValue().(FieldAccess).getTarget() = g
and g.getSourceDeclaration() = f
)
and not exists(MutatorOperation op |
op.getAnOperand().(FieldAccess).getTarget().getSourceDeclaration() = f
)
and exists(Field g |
fa.getTarget() = g
and g.getSourceDeclaration() = f
)
select f, "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.",
fa, "here"