Skip to content

Commit a373a52

Browse files
committed
Data flow: Move C# lambda flow logic into shared library
1 parent e1e4016 commit a373a52

File tree

11 files changed

+552
-147
lines changed

11 files changed

+552
-147
lines changed

csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/**
2+
* DEPRECATED.
3+
*
24
* Provides classes for data flow call contexts.
35
*/
46

@@ -15,39 +17,44 @@ private newtype TCallContext =
1517
TArgFunctionPointerCallContext(FunctionPointerCall fptrc, int i) { exists(fptrc.getArgument(i)) }
1618

1719
/**
20+
* DEPRECATED.
21+
*
1822
* A call context.
1923
*
2024
* A call context records the origin of data flow into callables.
2125
*/
22-
class CallContext extends TCallContext {
26+
deprecated class CallContext extends TCallContext {
2327
/** Gets a textual representation of this call context. */
2428
string toString() { none() }
2529

2630
/** Gets the location of this call context, if any. */
2731
Location getLocation() { none() }
2832
}
2933

30-
/** An empty call context. */
31-
class EmptyCallContext extends CallContext, TEmptyCallContext {
34+
/** DEPRECATED. An empty call context. */
35+
deprecated class EmptyCallContext extends CallContext, TEmptyCallContext {
3236
override string toString() { result = "<empty>" }
3337

3438
override EmptyLocation getLocation() { any() }
3539
}
3640

3741
/**
42+
* DEPRECATED.
43+
*
3844
* An argument call context, that is a call argument through which data flows
3945
* into a callable.
4046
*/
41-
abstract class ArgumentCallContext extends CallContext {
47+
abstract deprecated class ArgumentCallContext extends CallContext {
4248
/**
4349
* Holds if this call context represents the argument at position `i` of the
4450
* call expression `call`.
4551
*/
4652
abstract predicate isArgument(Expr call, int i);
4753
}
4854

49-
/** An argument of a non-delegate call. */
50-
class NonDelegateCallArgumentCallContext extends ArgumentCallContext, TArgNonDelegateCallContext {
55+
/** DEPRECATED. An argument of a non-delegate call. */
56+
deprecated class NonDelegateCallArgumentCallContext extends ArgumentCallContext,
57+
TArgNonDelegateCallContext {
5158
Expr arg;
5259

5360
NonDelegateCallArgumentCallContext() { this = TArgNonDelegateCallContext(arg) }
@@ -61,8 +68,8 @@ class NonDelegateCallArgumentCallContext extends ArgumentCallContext, TArgNonDel
6168
override Location getLocation() { result = arg.getLocation() }
6269
}
6370

64-
/** An argument of a delegate or function pointer call. */
65-
class DelegateLikeCallArgumentCallContext extends ArgumentCallContext {
71+
/** DEPRECATED. An argument of a delegate or function pointer call. */
72+
deprecated class DelegateLikeCallArgumentCallContext extends ArgumentCallContext {
6673
DelegateLikeCall dc;
6774
int arg;
6875

@@ -80,10 +87,10 @@ class DelegateLikeCallArgumentCallContext extends ArgumentCallContext {
8087
override Location getLocation() { result = dc.getArgument(arg).getLocation() }
8188
}
8289

83-
/** An argument of a delegate call. */
84-
class DelegateCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
90+
/** DEPRECATED. An argument of a delegate call. */
91+
deprecated class DelegateCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
8592
TArgDelegateCallContext { }
8693

87-
/** An argument of a function pointer call. */
88-
class FunctionPointerCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
94+
/** DEPRECATED. An argument of a function pointer call. */
95+
deprecated class FunctionPointerCallArgumentCallContext extends DelegateLikeCallArgumentCallContext,
8996
TArgFunctionPointerCallContext { }

csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 16 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
private import csharp
22
private import cil
33
private import dotnet
4+
private import DataFlowPublic
45
private import DataFlowPrivate
5-
private import DelegateDataFlow
66
private import FlowSummaryImpl as FlowSummaryImpl
77
private import semmle.code.csharp.dataflow.FlowSummary
88
private import semmle.code.csharp.dispatch.Dispatch
@@ -131,51 +131,24 @@ private module Cached {
131131
import Cached
132132

133133
private module DispatchImpl {
134-
private import CallContext
135-
136-
/**
137-
* Gets a viable run-time target for the delegate call `call`, requiring
138-
* call context `cc`.
139-
*/
140-
private DataFlowCallable viableDelegateCallable(DataFlowCall call, CallContext cc) {
141-
result = call.(DelegateDataFlowCall).getARuntimeTarget(cc)
142-
}
143-
144134
/**
145135
* Holds if the set of viable implementations that can be called by `call`
146136
* might be improved by knowing the call context. This is the case if the
147137
* call is a delegate call, or if the qualifier accesses a parameter of
148138
* the enclosing callable `c` (including the implicit `this` parameter).
149139
*/
150-
predicate mayBenefitFromCallContext(DataFlowCall call, Callable c) {
140+
predicate mayBenefitFromCallContext(NonDelegateDataFlowCall call, Callable c) {
151141
c = call.getEnclosingCallable() and
152-
(
153-
exists(CallContext cc | exists(viableDelegateCallable(call, cc)) |
154-
not cc instanceof EmptyCallContext
155-
)
156-
or
157-
call.(NonDelegateDataFlowCall).getDispatchCall().mayBenefitFromCallContext()
158-
)
142+
call.getDispatchCall().mayBenefitFromCallContext()
159143
}
160144

161145
/**
162146
* Gets a viable dispatch target of `call` in the context `ctx`. This is
163147
* restricted to those `call`s for which a context might make a difference.
164148
*/
165-
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
166-
exists(ArgumentCallContext cc | result = viableDelegateCallable(call, cc) |
167-
cc.isArgument(ctx.getExpr(), _)
168-
)
169-
or
170-
exists(DataFlowCallable enclosing |
171-
mayBenefitFromCallContext(call, enclosing) and
172-
ctx.getARuntimeTarget() = enclosing and
173-
result = viableDelegateCallable(call, any(EmptyCallContext ecc))
174-
)
175-
or
149+
DataFlowCallable viableImplInCallContext(NonDelegateDataFlowCall call, DataFlowCall ctx) {
176150
result =
177-
call.(NonDelegateDataFlowCall)
178-
.getDispatchCall()
151+
call.getDispatchCall()
179152
.getADynamicTargetInCallContext(ctx.(NonDelegateDataFlowCall).getDispatchCall())
180153
.getUnboundDeclaration()
181154
}
@@ -307,12 +280,7 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
307280
}
308281

309282
/** A delegate call relevant for data flow. */
310-
abstract class DelegateDataFlowCall extends DataFlowCall {
311-
/** Gets a viable run-time target of this call requiring call context `cc`. */
312-
abstract DataFlowCallable getARuntimeTarget(CallContext::CallContext cc);
313-
314-
override DataFlowCallable getARuntimeTarget() { result = this.getARuntimeTarget(_) }
315-
}
283+
abstract class DelegateDataFlowCall extends DataFlowCall { }
316284

317285
/** An explicit delegate or function pointer call relevant for data flow. */
318286
class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDelegateLikeCall {
@@ -321,8 +289,11 @@ class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDe
321289

322290
ExplicitDelegateLikeDataFlowCall() { this = TExplicitDelegateLikeCall(cfn, dc) }
323291

324-
override DataFlowCallable getARuntimeTarget(CallContext::CallContext cc) {
325-
result = getCallableForDataFlow(dc.getARuntimeTarget(cc))
292+
/** Gets the underlying call. */
293+
DelegateLikeCall getCall() { result = dc }
294+
295+
override DataFlowCallable getARuntimeTarget() {
296+
none() // handled by the shared library
326297
}
327298

328299
override ControlFlow::Nodes::ElementNode getControlFlowNode() { result = cfn }
@@ -395,11 +366,11 @@ class SummaryDelegateCall extends DelegateDataFlowCall, TSummaryDelegateCall {
395366

396367
SummaryDelegateCall() { this = TSummaryDelegateCall(c, pos) }
397368

398-
override DataFlowCallable getARuntimeTarget(CallContext::CallContext cc) {
399-
exists(SummaryDelegateParameterSink p |
400-
p.isParameterOf(c, pos) and
401-
result = p.getARuntimeTarget(cc)
402-
)
369+
/** Gets the parameter node that this delegate call targets. */
370+
ParameterNode getParameterNode() { result.isParameterOf(c, pos) }
371+
372+
override DataFlowCallable getARuntimeTarget() {
373+
none() // handled by the shared library
403374
}
404375

405376
override ControlFlow::Nodes::ElementNode getControlFlowNode() { none() }

0 commit comments

Comments
 (0)