11private import csharp
2- private import semmle.code.csharp.commons.Collections as Collections
2+ private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections
33private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
44private import semmle.code.csharp.frameworks.system.linq.Expressions
55private import CaptureModelsSpecific as Specific
66private import CaptureModels
77
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+
820/**
921 * A class of callables that are relevant generating summaries for based
1022 * on the Theorems for Free approach.
@@ -16,69 +28,78 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
1628 t = this .getDeclaringType ( ) .( UnboundGeneric ) .getATypeParameter ( )
1729 }
1830
19- private predicate isMethodTypeParameter ( TypeParameter t ) {
20- t = this .( UnboundGeneric ) .getATypeParameter ( )
21- }
22-
2331 bindingset [ t]
2432 private string getAccess ( TypeParameter t ) {
2533 exists ( string access |
26- if Collections :: isCollectionType ( this .getDeclaringType ( ) )
34+ if isGenericCollectionType ( this .getDeclaringType ( ) , t )
2735 then access = ".Element"
28- else access = ""
36+ else access = ".SyntheticField[Arg" + t . getName ( ) + "] "
2937 |
30- result = Specific:: qualifierString ( ) + ".SyntheticField[Arg" + t . getName ( ) + "]" + access
38+ result = Specific:: qualifierString ( ) + access
3139 )
3240 }
3341
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+ }
3560
61+ /**
62+ * Holds if `this` has a parameter `p`, which is of type `t`
63+ * or collection of type `t`.
64+ */
3665 private predicate parameter ( TypeParameter t , Parameter p ) {
3766 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+ )
3974 }
4075
4176 /**
4277 * Gets the string representation of a summary for `this`, where this has a signature like
43- * this : T -> unit
78+ * this : T -> S
4479 * where T is type parameter for the class declaring `this`.
80+ * Important cases are S = unit (setter) and S = T (both getter and setter).
4581 */
4682 private string getSetterSummary ( ) {
4783 exists ( TypeParameter t , Parameter p |
4884 this .isClassTypeParameter ( t ) and
49- this .getReturnType ( ) instanceof VoidType and
5085 this .parameter ( t , p )
5186 |
52- result = asTaintModel ( this , Specific:: parameterAccess ( p ) , this .getAccess ( t ) )
87+ result = asValueModel ( this , Specific:: parameterAccess ( p ) , this .getAccess ( t ) )
5388 )
5489 }
5590
5691 /**
5792 * Gets the string representation of a summary for `this`, where this has a signature like
58- * this : unit -> T
93+ * this : S -> T
5994 * where T is type parameter for the class declaring `this`.
95+ * Important cases are S = unit (getter) and S = T (both getter and setter).
6096 */
6197 private string getGetterSummary ( ) {
6298 exists ( TypeParameter t |
6399 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 )
80101 |
81- result = asTaintModel ( this , Specific :: parameterAccess ( p ) , "ReturnValue" )
102+ result = asValueModel ( this , this . getAccess ( t ) , this . getReturnAccess ( t ) )
82103 )
83104 }
84105
@@ -95,7 +116,7 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
95116 p2 .getType ( ) = t
96117 |
97118 result =
98- asTaintModel ( this , this .getAccess ( t ) ,
119+ asValueModel ( this , this .getAccess ( t ) ,
99120 Specific:: parameterAccess ( p1 ) + ".Parameter[" + p2 .getPosition ( ) + "]" )
100121 )
101122 }
@@ -104,11 +125,7 @@ class TheoremTargetApi extends Specific::TargetApiSpecific {
104125 * Gets the string representation of all summaries based on the Theorems for Free approach.
105126 */
106127 string getSummaries ( ) {
107- result =
108- [
109- this .getSetterSummary ( ) , this .getGetterSummary ( ) , this .getTransformSummary ( ) ,
110- this .getApplySummary ( )
111- ]
128+ result = [ this .getSetterSummary ( ) , this .getGetterSummary ( ) , this .getApplySummary ( ) ]
112129 }
113130}
114131
0 commit comments