-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathExposeRepresentation.ql
More file actions
76 lines (67 loc) · 2.43 KB
/
ExposeRepresentation.ql
File metadata and controls
76 lines (67 loc) · 2.43 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
/**
* @name Exposing internal representation
* @description An object that accidentally exposes its internal representation may allow the
* object's fields to be modified in ways that the object is not prepared to handle.
* @kind problem
* @problem.severity recommendation
* @precision high
* @id cs/expose-implementation
* @tags reliability
* external/cwe/cwe-485
*/
import csharp
import semmle.code.csharp.commons.Collections
import DataFlow
predicate storesCollection(Callable c, Parameter p, Field f) {
f.getDeclaringType() = c.getDeclaringType().getABaseType*().getUnboundDeclaration() and
f.getType() instanceof CollectionType and
p = c.getAParameter() and
f.getAnAssignedValue() = p.getAnAccess() and
not c.(Modifiable).isStatic()
}
predicate returnsCollection(Callable c, Field f) {
f.getDeclaringType() = c.getDeclaringType().getABaseType*().getUnboundDeclaration() and
f.getType() instanceof CollectionType and
c.canReturn(f.getAnAccess()) and
not c.(Modifiable).isStatic()
}
predicate mayWriteToCollection(Expr modified) {
modified instanceof CollectionModificationAccess
or
exists(Expr mid | mayWriteToCollection(mid) | localExprFlow(modified, mid))
or
exists(MethodCall mid, Callable c | mayWriteToCollection(mid) |
mid.getTarget() = c and
c.canReturn(modified)
)
}
predicate modificationAfter(Expr before, Expr after) {
mayWriteToCollection(after) and
localFlowStep+(exprNode(before), exprNode(after))
}
VariableAccess varPassedInto(Callable c, Parameter p) {
exists(Call call | call.getTarget() = c | call.getArgumentForParameter(p) = result)
}
predicate exposesByReturn(Callable c, Field f, Expr why, string whyText) {
returnsCollection(c, f) and
exists(MethodCall ma | ma.getTarget() = c |
mayWriteToCollection(ma) and
why = ma and
whyText = "after this call to " + c.getName()
)
}
predicate exposesByStore(Callable c, Field f, Expr why, string whyText) {
exists(VariableAccess v, Parameter p |
storesCollection(c, p, f) and
v = varPassedInto(c, p) and
modificationAfter(v, why) and
whyText = "through the variable " + v.getTarget().getName()
)
}
from Callable c, Field f, Expr why, string whyText
where
exposesByReturn(c, f, why, whyText) or
exposesByStore(c, f, why, whyText)
select c,
"'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() +
"'. The value may be modified $@.", why.getLocation(), whyText