@@ -13,6 +13,7 @@ private import semmle.code.csharp.Unification
13
13
private import semmle.code.csharp.controlflow.Guards
14
14
private import semmle.code.csharp.dispatch.Dispatch
15
15
private import semmle.code.csharp.frameworks.EntityFramework
16
+ private import semmle.code.csharp.frameworks.system.linq.Expressions
16
17
private import semmle.code.csharp.frameworks.NHibernate
17
18
private import semmle.code.csharp.frameworks.Razor
18
19
private import semmle.code.csharp.frameworks.system.Collections
@@ -1146,7 +1147,18 @@ private module Cached {
1146
1147
TPrimaryConstructorParameterContent ( Parameter p ) {
1147
1148
p .getCallable ( ) instanceof PrimaryConstructor
1148
1149
} or
1149
- TCapturedVariableContent ( VariableCapture:: CapturedVariable v )
1150
+ TCapturedVariableContent ( VariableCapture:: CapturedVariable v ) or
1151
+ TDelegateCallArgumentContent ( Parameter p , int i ) {
1152
+ i =
1153
+ [ 0 .. p .getType ( )
1154
+ .getUnboundDeclaration ( )
1155
+ .( SystemLinqExpressions:: DelegateExtType )
1156
+ .getDelegateType ( )
1157
+ .getNumberOfParameters ( ) - 1 ]
1158
+ } or
1159
+ TDelegateCallReturnContent ( Parameter p ) {
1160
+ p .getType ( ) .getUnboundDeclaration ( ) instanceof SystemLinqExpressions:: DelegateExtType
1161
+ }
1150
1162
1151
1163
cached
1152
1164
newtype TContentSet =
@@ -1162,7 +1174,13 @@ private module Cached {
1162
1174
TPrimaryConstructorParameterApproxContent ( string firstChar ) {
1163
1175
firstChar = approximatePrimaryConstructorParameterContent ( _)
1164
1176
} or
1165
- TCapturedVariableContentApprox ( VariableCapture:: CapturedVariable v )
1177
+ TCapturedVariableContentApprox ( VariableCapture:: CapturedVariable v ) or
1178
+ TDelegateCallArgumentApproxContent ( string firstChar ) {
1179
+ firstChar = approximateDelegateCallArgumentContent ( _)
1180
+ } or
1181
+ TDelegateCallReturnApproxContent ( string firstChar ) {
1182
+ firstChar = approximateDelegateCallReturnContent ( _)
1183
+ }
1166
1184
1167
1185
pragma [ nomagic]
1168
1186
private predicate commonSubTypeGeneral ( DataFlowTypeOrUnifiable t1 , RelevantGvnType t2 ) {
@@ -2273,6 +2291,22 @@ private predicate recordProperty(RecordType t, ContentSet c, string name) {
2273
2291
)
2274
2292
}
2275
2293
2294
+ /**
2295
+ * Holds if data can flow from `node1` to `node2` via an assignment to
2296
+ * the content set `c` of a delegate call.
2297
+ *
2298
+ * If there is a delegate call f(x), then we store "x" on "f"
2299
+ * using a delegate parameter content set.
2300
+ */
2301
+ private predicate storeStepDelegateCall ( Node node1 , ContentSet c , Node node2 ) {
2302
+ exists ( DelegateCall call , Parameter p , int i |
2303
+ node1 .asExpr ( ) = call .getArgument ( i ) and
2304
+ node2 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) = call .getExpr ( ) and
2305
+ call .getExpr ( ) = p .getAnAccess ( ) and
2306
+ c .isDelegateCallArgument ( p , i )
2307
+ )
2308
+ }
2309
+
2276
2310
/**
2277
2311
* Holds if data can flow from `node1` to `node2` via an assignment to
2278
2312
* content `c`.
@@ -2305,6 +2339,8 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
2305
2339
or
2306
2340
FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2307
2341
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2342
+ or
2343
+ storeStepDelegateCall ( node1 , c , node2 )
2308
2344
}
2309
2345
2310
2346
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -2425,6 +2461,22 @@ private predicate readContentStep(Node node1, Content c, Node node2) {
2425
2461
VariableCapture:: readStep ( node1 , c , node2 )
2426
2462
}
2427
2463
2464
+ /**
2465
+ * Holds if data can flow from `node1` to `node2` via an assignment to
2466
+ * the content set `c` of a delegate call.
2467
+ *
2468
+ * If there is a delegate call f(x), then we read the result of the delegate
2469
+ * call.
2470
+ */
2471
+ private predicate readStepDelegateCall ( Node node1 , ContentSet c , Node node2 ) {
2472
+ exists ( DelegateCall call , Parameter p |
2473
+ node1 .asExpr ( ) = call .getExpr ( ) and
2474
+ node2 .asExpr ( ) = call and
2475
+ call .getExpr ( ) = p .getAnAccess ( ) and
2476
+ c .isDelegateCallReturn ( p )
2477
+ )
2478
+ }
2479
+
2428
2480
/**
2429
2481
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
2430
2482
*/
@@ -2443,6 +2495,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2443
2495
or
2444
2496
FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2445
2497
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2498
+ or
2499
+ readStepDelegateCall ( node1 , c , node2 )
2446
2500
}
2447
2501
2448
2502
private predicate clearsCont ( Node n , Content c ) {
@@ -3037,6 +3091,16 @@ class ContentApprox extends TContentApprox {
3037
3091
exists ( VariableCapture:: CapturedVariable v |
3038
3092
this = TCapturedVariableContentApprox ( v ) and result = "captured " + v
3039
3093
)
3094
+ or
3095
+ exists ( string firstChar |
3096
+ this = TDelegateCallArgumentApproxContent ( firstChar ) and
3097
+ result = "approximated delegate call argument " + firstChar
3098
+ )
3099
+ or
3100
+ exists ( string firstChar |
3101
+ this = TDelegateCallReturnApproxContent ( firstChar ) and
3102
+ result = "approximated delegate call return " + firstChar
3103
+ )
3040
3104
}
3041
3105
}
3042
3106
@@ -3058,6 +3122,22 @@ private string approximatePrimaryConstructorParameterContent(PrimaryConstructorP
3058
3122
result = pc .getParameter ( ) .getName ( ) .prefix ( 1 )
3059
3123
}
3060
3124
3125
+ private string getApproximateParameterName ( Parameter p ) {
3126
+ exists ( string name | name = p .getName ( ) |
3127
+ name = "" and result = ""
3128
+ or
3129
+ result = name .prefix ( 1 )
3130
+ )
3131
+ }
3132
+
3133
+ private string approximateDelegateCallArgumentContent ( DelegateCallArgumentContent dc ) {
3134
+ result = getApproximateParameterName ( dc .getParameter ( ) )
3135
+ }
3136
+
3137
+ private string approximateDelegateCallReturnContent ( DelegateCallReturnContent dc ) {
3138
+ result = getApproximateParameterName ( dc .getParameter ( ) )
3139
+ }
3140
+
3061
3141
/** Gets an approximated value for content `c`. */
3062
3142
pragma [ nomagic]
3063
3143
ContentApprox getContentApprox ( Content c ) {
@@ -3073,6 +3153,10 @@ ContentApprox getContentApprox(Content c) {
3073
3153
TPrimaryConstructorParameterApproxContent ( approximatePrimaryConstructorParameterContent ( c ) )
3074
3154
or
3075
3155
result = TCapturedVariableContentApprox ( VariableCapture:: getCapturedVariableContent ( c ) )
3156
+ or
3157
+ result = TDelegateCallArgumentApproxContent ( approximateDelegateCallArgumentContent ( c ) )
3158
+ or
3159
+ result = TDelegateCallReturnApproxContent ( approximateDelegateCallReturnContent ( c ) )
3076
3160
}
3077
3161
3078
3162
/**
0 commit comments