@@ -14,8 +14,14 @@ private import semmle.code.csharp.dataflow.FlowSummary
1414private import semmle.code.csharp.dispatch.Dispatch
1515private import semmle.code.csharp.frameworks.system.linq.Expressions
1616
17+ /** A source of flow for a delegate or function pointer expression. */
18+ private class DelegateLikeFlowSource extends DataFlow:: ExprNode {
19+ /** Gets the callable that is referenced in this delegate or function pointer flow source. */
20+ Callable getCallable ( ) { none ( ) }
21+ }
22+
1723/** A source of flow for a delegate expression. */
18- private class DelegateFlowSource extends DataFlow :: ExprNode {
24+ private class DelegateFlowSource extends DelegateLikeFlowSource {
1925 Callable c ;
2026
2127 DelegateFlowSource ( ) {
@@ -27,11 +33,26 @@ private class DelegateFlowSource extends DataFlow::ExprNode {
2733 }
2834
2935 /** Gets the callable that is referenced in this delegate flow source. */
30- Callable getCallable ( ) { result = c }
36+ override Callable getCallable ( ) { result = c }
37+ }
38+
39+ /** A source of flow for a function pointer expression. */
40+ private class FunctionPointerFlowSource extends DelegateLikeFlowSource {
41+ Callable c ;
42+
43+ FunctionPointerFlowSource ( ) {
44+ this .getExpr ( ) =
45+ any ( Expr e |
46+ c = e .( AddressOfExpr ) .getOperand ( ) .( CallableAccess ) .getTarget ( ) .getUnboundDeclaration ( )
47+ )
48+ }
49+
50+ /** Gets the callable that is referenced in this function pointer flow source. */
51+ override Callable getCallable ( ) { result = c }
3152}
3253
33- /** A sink of flow for a delegate expression. */
34- abstract private class DelegateFlowSink extends DataFlow:: Node {
54+ /** A sink of flow for a delegate or function pointer expression. */
55+ abstract private class DelegateLikeFlowSink extends DataFlow:: Node {
3556 /**
3657 * Gets an actual run-time target of this delegate call in the given call
3758 * context, if any. The call context records the *last* call required to
@@ -85,33 +106,49 @@ abstract private class DelegateFlowSink extends DataFlow::Node {
85106 */
86107 cached
87108 Callable getARuntimeTarget ( CallContext context ) {
88- exists ( DelegateFlowSource dfs |
109+ exists ( DelegateLikeFlowSource dfs |
89110 flowsFrom ( this , dfs , _, context ) and
90111 result = dfs .getCallable ( )
91112 )
92113 }
93114}
94115
116+ /** A delegate or function pointer call expression. */
117+ class DelegateLikeCallExpr extends DelegateLikeFlowSink , DataFlow:: ExprNode {
118+ /** Gets the delegate or function pointer call that this expression belongs to. */
119+ DelegateLikeCall getCall ( ) { none ( ) }
120+ }
121+
95122/** A delegate call expression. */
96- class DelegateCallExpr extends DelegateFlowSink , DataFlow :: ExprNode {
123+ class DelegateCallExpr extends DelegateLikeCallExpr {
97124 DelegateCall dc ;
98125
99- DelegateCallExpr ( ) { this .getExpr ( ) = dc .getDelegateExpr ( ) }
126+ DelegateCallExpr ( ) { this .getExpr ( ) = dc .getExpr ( ) }
100127
101128 /** Gets the delegate call that this expression belongs to. */
102- DelegateCall getDelegateCall ( ) { result = dc }
129+ override DelegateCall getCall ( ) { result = dc }
130+ }
131+
132+ /** A function pointer call expression. */
133+ class FunctionPointerCallExpr extends DelegateLikeCallExpr {
134+ FunctionPointerCall fptrc ;
135+
136+ FunctionPointerCallExpr ( ) { this .getExpr ( ) = fptrc .getExpr ( ) }
137+
138+ /** Gets the function pointer call that this expression belongs to. */
139+ override FunctionPointerCall getCall ( ) { result = fptrc }
103140}
104141
105142/** A parameter of delegate type belonging to a callable with a flow summary. */
106- class SummaryDelegateParameterSink extends DelegateFlowSink , ParameterNode {
143+ class SummaryDelegateParameterSink extends DelegateLikeFlowSink , ParameterNode {
107144 SummaryDelegateParameterSink ( ) {
108145 this .getType ( ) instanceof SystemLinqExpressions:: DelegateExtType and
109146 this .isParameterOf ( any ( SummarizedCallable c ) , _)
110147 }
111148}
112149
113150/** A delegate expression that is added to an event. */
114- class AddEventSource extends DelegateFlowSink , DataFlow:: ExprNode {
151+ class AddEventSource extends DelegateLikeFlowSink , DataFlow:: ExprNode {
115152 AddEventExpr ae ;
116153
117154 AddEventSource ( ) { this .getExpr ( ) = ae .getRValue ( ) }
@@ -150,7 +187,7 @@ private class NormalReturnNode extends Node {
150187 * records the last call on the path from `node` to `sink`, if any.
151188 */
152189private predicate flowsFrom (
153- DelegateFlowSink sink , DataFlow:: Node node , boolean isReturned , CallContext lastCall
190+ DelegateLikeFlowSink sink , DataFlow:: Node node , boolean isReturned , CallContext lastCall
154191) {
155192 // Base case
156193 sink = node and
@@ -188,7 +225,8 @@ private predicate flowsFrom(
188225 or
189226 // Flow into a callable (delegate call)
190227 exists (
191- ParameterNode mid , CallContext prevLastCall , DelegateCall call , Callable c , Parameter p , int i
228+ ParameterNode mid , CallContext prevLastCall , DelegateLikeCall call , Callable c , Parameter p ,
229+ int i
192230 |
193231 flowsFrom ( sink , mid , isReturned , prevLastCall ) and
194232 isReturned = false and
@@ -238,14 +276,14 @@ private predicate flowIntoNonDelegateCall(NonDelegateCall call, Expr arg, DotNet
238276}
239277
240278pragma [ noinline]
241- private predicate flowIntoDelegateCall ( DelegateCall call , Callable c , Expr arg , int i ) {
242- exists ( DelegateFlowSource dfs , DelegateCallExpr dce |
279+ private predicate flowIntoDelegateCall ( DelegateLikeCall call , Callable c , Expr arg , int i ) {
280+ exists ( DelegateLikeFlowSource dfs , DelegateLikeCallExpr dce |
243281 // the call context is irrelevant because the delegate call
244282 // itself will be the context
245283 flowsFrom ( dce , dfs , _, _) and
246284 arg = call .getArgument ( i ) and
247285 c = dfs .getCallable ( ) and
248- call = dce .getDelegateCall ( )
286+ call = dce .getCall ( )
249287 )
250288}
251289
@@ -255,11 +293,13 @@ private predicate flowOutOfNonDelegateCall(NonDelegateCall call, NormalReturnNod
255293}
256294
257295pragma [ noinline]
258- private predicate flowOutOfDelegateCall ( DelegateCall dc , NormalReturnNode ret , CallContext lastCall ) {
259- exists ( DelegateFlowSource dfs , DelegateCallExpr dce , Callable c |
296+ private predicate flowOutOfDelegateCall (
297+ DelegateLikeCall dc , NormalReturnNode ret , CallContext lastCall
298+ ) {
299+ exists ( DelegateLikeFlowSource dfs , DelegateLikeCallExpr dce , Callable c |
260300 flowsFrom ( dce , dfs , _, lastCall ) and
261301 ret .getEnclosingCallable ( ) = c and
262302 c = dfs .getCallable ( ) and
263- dc = dce .getDelegateCall ( )
303+ dc = dce .getCall ( )
264304 )
265305}
0 commit comments