@@ -13,6 +13,7 @@ private import semmle.code.csharp.Unification
1313private import semmle.code.csharp.controlflow.Guards
1414private import semmle.code.csharp.dispatch.Dispatch
1515private import semmle.code.csharp.frameworks.EntityFramework
16+ private import semmle.code.csharp.frameworks.system.linq.Expressions
1617private import semmle.code.csharp.frameworks.NHibernate
1718private import semmle.code.csharp.frameworks.Razor
1819private import semmle.code.csharp.frameworks.system.Collections
@@ -1146,7 +1147,18 @@ private module Cached {
11461147 TPrimaryConstructorParameterContent ( Parameter p ) {
11471148 p .getCallable ( ) instanceof PrimaryConstructor
11481149 } 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+ }
11501162
11511163 cached
11521164 newtype TContentSet =
@@ -1162,7 +1174,13 @@ private module Cached {
11621174 TPrimaryConstructorParameterApproxContent ( string firstChar ) {
11631175 firstChar = approximatePrimaryConstructorParameterContent ( _)
11641176 } 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+ }
11661184
11671185 pragma [ nomagic]
11681186 private predicate commonSubTypeGeneral ( DataFlowTypeOrUnifiable t1 , RelevantGvnType t2 ) {
@@ -2273,6 +2291,22 @@ private predicate recordProperty(RecordType t, ContentSet c, string name) {
22732291 )
22742292}
22752293
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+
22762310/**
22772311 * Holds if data can flow from `node1` to `node2` via an assignment to
22782312 * content `c`.
@@ -2305,6 +2339,8 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
23052339 or
23062340 FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
23072341 node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2342+ or
2343+ storeStepDelegateCall ( node1 , c , node2 )
23082344}
23092345
23102346private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -2425,6 +2461,22 @@ private predicate readContentStep(Node node1, Content c, Node node2) {
24252461 VariableCapture:: readStep ( node1 , c , node2 )
24262462}
24272463
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+
24282480/**
24292481 * Holds if data can flow from `node1` to `node2` via a read of content `c`.
24302482 */
@@ -2443,6 +2495,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
24432495 or
24442496 FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
24452497 node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2498+ or
2499+ readStepDelegateCall ( node1 , c , node2 )
24462500}
24472501
24482502private predicate clearsCont ( Node n , Content c ) {
@@ -3037,6 +3091,16 @@ class ContentApprox extends TContentApprox {
30373091 exists ( VariableCapture:: CapturedVariable v |
30383092 this = TCapturedVariableContentApprox ( v ) and result = "captured " + v
30393093 )
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+ )
30403104 }
30413105}
30423106
@@ -3058,6 +3122,22 @@ private string approximatePrimaryConstructorParameterContent(PrimaryConstructorP
30583122 result = pc .getParameter ( ) .getName ( ) .prefix ( 1 )
30593123}
30603124
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+
30613141/** Gets an approximated value for content `c`. */
30623142pragma [ nomagic]
30633143ContentApprox getContentApprox ( Content c ) {
@@ -3073,6 +3153,10 @@ ContentApprox getContentApprox(Content c) {
30733153 TPrimaryConstructorParameterApproxContent ( approximatePrimaryConstructorParameterContent ( c ) )
30743154 or
30753155 result = TCapturedVariableContentApprox ( VariableCapture:: getCapturedVariableContent ( c ) )
3156+ or
3157+ result = TDelegateCallArgumentApproxContent ( approximateDelegateCallArgumentContent ( c ) )
3158+ or
3159+ result = TDelegateCallReturnApproxContent ( approximateDelegateCallReturnContent ( c ) )
30763160}
30773161
30783162/**
0 commit comments