1
1
private import csharp
2
- private import semmle.code.csharp.commons.Collections as Collections
2
+ private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections
3
3
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
4
4
private import semmle.code.csharp.frameworks.system.linq.Expressions
5
5
private import CaptureModelsSpecific as Specific
6
6
private import CaptureModels
7
7
8
+ /**
9
+ * Holds if `t` is a subtype (reflexive/transitive) of `IEnumerable<T>`, where `T` = `tp`.
10
+ */
11
+ private predicate isGenericCollectionType ( ValueOrRefType t , TypeParameter tp ) {
12
+ exists ( ConstructedGeneric t2 |
13
+ t2 = t .getABaseType * ( ) and
14
+ t2 .getUnboundDeclaration ( ) instanceof
15
+ GenericCollections:: SystemCollectionsGenericIEnumerableTInterface and
16
+ tp = t2 .getATypeArgument ( )
17
+ )
18
+ }
19
+
8
20
/**
9
21
* A class of callables that are relevant generating summaries for based
10
22
* on the Theorems for Free approach.
@@ -16,69 +28,78 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
16
28
t = this .getDeclaringType ( ) .( UnboundGeneric ) .getATypeParameter ( )
17
29
}
18
30
19
- private predicate isMethodTypeParameter ( TypeParameter t ) {
20
- t = this .( UnboundGeneric ) .getATypeParameter ( )
21
- }
22
-
23
31
bindingset [ t]
24
32
private string getAccess ( TypeParameter t ) {
25
33
exists ( string access |
26
- if Collections :: isCollectionType ( this .getDeclaringType ( ) )
34
+ if isGenericCollectionType ( this .getDeclaringType ( ) , t )
27
35
then access = ".Element"
28
- else access = ""
36
+ else access = ".SyntheticField[Arg" + t . getName ( ) + "] "
29
37
|
30
- result = Specific:: qualifierString ( ) + ".SyntheticField[Arg" + t . getName ( ) + "]" + access
38
+ result = Specific:: qualifierString ( ) + access
31
39
)
32
40
}
33
41
34
- private predicate returns ( TypeParameter t ) { this .getReturnType ( ) = t }
42
+ bindingset [ t]
43
+ private string getReturnAccess ( TypeParameter t ) {
44
+ exists ( string access |
45
+ (
46
+ if isGenericCollectionType ( this .getReturnType ( ) , t )
47
+ then access = ".Element"
48
+ else access = ""
49
+ ) and
50
+ result = "ReturnValue" + access
51
+ )
52
+ }
53
+
54
+ /**
55
+ * Holds if `this` returns a value of type `t` or a collection of type `t`.
56
+ */
57
+ private predicate returns ( TypeParameter t ) {
58
+ this .getReturnType ( ) = t or isGenericCollectionType ( this .getReturnType ( ) , t )
59
+ }
35
60
61
+ /**
62
+ * Holds if `this` has a parameter `p`, which is of type `t`
63
+ * or collection of type `t`.
64
+ */
36
65
private predicate parameter ( TypeParameter t , Parameter p ) {
37
66
p = this .getAParameter ( ) and
38
- p .getType ( ) = t
67
+ (
68
+ // Parameter of type t
69
+ p .getType ( ) = t
70
+ or
71
+ // Parameter is a collection of type t
72
+ isGenericCollectionType ( p .getType ( ) , t )
73
+ )
39
74
}
40
75
41
76
/**
42
77
* Gets the string representation of a summary for `this`, where this has a signature like
43
- * this : T -> unit
78
+ * this : T -> S
44
79
* where T is type parameter for the class declaring `this`.
80
+ * Important cases are S = unit (setter) and S = T (both getter and setter).
45
81
*/
46
82
private string getSetterSummary ( ) {
47
83
exists ( TypeParameter t , Parameter p |
48
84
this .isClassTypeParameter ( t ) and
49
- this .getReturnType ( ) instanceof VoidType and
50
85
this .parameter ( t , p )
51
86
|
52
- result = asTaintModel ( this , Specific:: parameterAccess ( p ) , this .getAccess ( t ) )
87
+ result = asValueModel ( this , Specific:: parameterAccess ( p ) , this .getAccess ( t ) )
53
88
)
54
89
}
55
90
56
91
/**
57
92
* Gets the string representation of a summary for `this`, where this has a signature like
58
- * this : unit -> T
93
+ * this : S -> T
59
94
* where T is type parameter for the class declaring `this`.
95
+ * Important cases are S = unit (getter) and S = T (both getter and setter).
60
96
*/
61
97
private string getGetterSummary ( ) {
62
98
exists ( TypeParameter t |
63
99
this .isClassTypeParameter ( t ) and
64
- this .returns ( t ) and
65
- not this .parameter ( t , _)
66
- |
67
- result = asTaintModel ( this , this .getAccess ( t ) , "ReturnValue" )
68
- )
69
- }
70
-
71
- /**
72
- * Gets the string representation of a summary for `this`, where this has a signature like
73
- * this : T -> T
74
- */
75
- private string getTransformSummary ( ) {
76
- exists ( TypeParameter t , Parameter p |
77
- ( this .isClassTypeParameter ( t ) or this .isMethodTypeParameter ( t ) ) and
78
- this .returns ( t ) and
79
- this .parameter ( t , p )
100
+ this .returns ( t )
80
101
|
81
- result = asTaintModel ( this , Specific :: parameterAccess ( p ) , "ReturnValue" )
102
+ result = asValueModel ( this , this . getAccess ( t ) , this . getReturnAccess ( t ) )
82
103
)
83
104
}
84
105
@@ -95,7 +116,7 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
95
116
p2 .getType ( ) = t
96
117
|
97
118
result =
98
- asTaintModel ( this , this .getAccess ( t ) ,
119
+ asValueModel ( this , this .getAccess ( t ) ,
99
120
Specific:: parameterAccess ( p1 ) + ".Parameter[" + p2 .getPosition ( ) + "]" )
100
121
)
101
122
}
@@ -104,11 +125,7 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
104
125
* Gets the string representation of all summaries based on the Theorems for Free approach.
105
126
*/
106
127
string getSummaries ( ) {
107
- result =
108
- [
109
- this .getSetterSummary ( ) , this .getGetterSummary ( ) , this .getTransformSummary ( ) ,
110
- this .getApplySummary ( )
111
- ]
128
+ result = [ this .getSetterSummary ( ) , this .getGetterSummary ( ) , this .getApplySummary ( ) ]
112
129
}
113
130
}
114
131
0 commit comments