@@ -12,14 +12,6 @@ private import semmle.code.csharp.dispatch.RuntimeCallable
12
12
private import semmle.code.csharp.frameworks.system.Collections
13
13
private import semmle.code.csharp.frameworks.system.collections.Generic
14
14
15
- private predicate summarizedCallable ( DataFlowCallable c ) {
16
- c instanceof FlowSummary:: SummarizedCallable
17
- or
18
- FlowSummaryImpl:: Private:: summaryReturnNode ( _, TJumpReturnKind ( c , _) )
19
- or
20
- c = interpretElement ( _, _, _, _, _, _)
21
- }
22
-
23
15
/**
24
16
* Gets a source declaration of callable `c` that has a body or has
25
17
* a flow summary.
@@ -29,9 +21,6 @@ private predicate summarizedCallable(DataFlowCallable c) {
29
21
*/
30
22
DotNet:: Callable getCallableForDataFlow ( DotNet:: Callable c ) {
31
23
exists ( DotNet:: Callable unboundDecl | unboundDecl = c .getUnboundDeclaration ( ) |
32
- summarizedCallable ( unboundDecl ) and
33
- result = unboundDecl
34
- or
35
24
result .hasBody ( ) and
36
25
if unboundDecl .getFile ( ) .fromSource ( )
37
26
then
@@ -81,17 +70,27 @@ newtype TReturnKind =
81
70
v = def .getSourceVariable ( ) .getAssignable ( )
82
71
)
83
72
} or
84
- TJumpReturnKind ( DataFlowCallable target , ReturnKind rk ) {
85
- rk instanceof NormalReturnKind and
73
+ TJumpReturnKind ( Callable target , ReturnKind rk ) {
74
+ target . isUnboundDeclaration ( ) and
86
75
(
87
- target instanceof Constructor or
88
- not target .getReturnType ( ) instanceof VoidType
76
+ rk instanceof NormalReturnKind and
77
+ (
78
+ target instanceof Constructor or
79
+ not target .getReturnType ( ) instanceof VoidType
80
+ )
81
+ or
82
+ exists ( target .getParameter ( rk .( OutRefReturnKind ) .getPosition ( ) ) )
89
83
)
90
- or
91
- exists ( target .getParameter ( rk .( OutRefReturnKind ) .getPosition ( ) ) )
92
84
}
93
85
94
86
private module Cached {
87
+ cached
88
+ newtype TDataFlowCallable =
89
+ TDotNetCallable ( DotNet:: Callable c ) {
90
+ c .isUnboundDeclaration ( ) and not c instanceof FlowSummary:: SummarizedCallable
91
+ } or
92
+ TSummarizedCallable ( FlowSummary:: SummarizedCallable c )
93
+
95
94
cached
96
95
newtype TDataFlowCall =
97
96
TNonDelegateCall ( ControlFlow:: Nodes:: ElementNode cfn , DispatchCall dc ) {
@@ -108,7 +107,7 @@ private module Cached {
108
107
// No need to include calls that are compiled from source
109
108
not call .getImplementation ( ) .getMethod ( ) .compiledFromSource ( )
110
109
} or
111
- TSummaryCall ( FlowSummary :: SummarizedCallable c , Node receiver ) {
110
+ TSummaryCall ( FlowSummaryImpl :: Public :: SummarizedCallable c , Node receiver ) {
112
111
FlowSummaryImpl:: Private:: summaryCallbackRange ( c , receiver )
113
112
}
114
113
@@ -144,7 +143,7 @@ private module DispatchImpl {
144
143
* call is a delegate call, or if the qualifier accesses a parameter of
145
144
* the enclosing callable `c` (including the implicit `this` parameter).
146
145
*/
147
- predicate mayBenefitFromCallContext ( NonDelegateDataFlowCall call , Callable c ) {
146
+ predicate mayBenefitFromCallContext ( NonDelegateDataFlowCall call , DataFlowCallable c ) {
148
147
c = call .getEnclosingCallable ( ) and
149
148
call .getDispatchCall ( ) .mayBenefitFromCallContext ( )
150
149
}
@@ -154,7 +153,7 @@ private module DispatchImpl {
154
153
* restricted to those `call`s for which a context might make a difference.
155
154
*/
156
155
DataFlowCallable viableImplInCallContext ( NonDelegateDataFlowCall call , DataFlowCall ctx ) {
157
- result =
156
+ result . getUnderlyingCallable ( ) =
158
157
call .getDispatchCall ( )
159
158
.getADynamicTargetInCallContext ( ctx .( NonDelegateDataFlowCall ) .getDispatchCall ( ) )
160
159
.getUnboundDeclaration ( )
@@ -233,22 +232,38 @@ class ImplicitCapturedReturnKind extends ReturnKind, TImplicitCapturedReturnKind
233
232
* one API entry point and out of another.
234
233
*/
235
234
class JumpReturnKind extends ReturnKind , TJumpReturnKind {
236
- private DataFlowCallable target ;
235
+ private Callable target ;
237
236
private ReturnKind rk ;
238
237
239
238
JumpReturnKind ( ) { this = TJumpReturnKind ( target , rk ) }
240
239
241
240
/** Gets the target of the jump. */
242
- DataFlowCallable getTarget ( ) { result = target }
241
+ Callable getTarget ( ) { result = target }
243
242
244
243
/** Gets the return kind of the target. */
245
244
ReturnKind getTargetReturnKind ( ) { result = rk }
246
245
247
246
override string toString ( ) { result = "jump to " + target }
248
247
}
249
248
250
- class DataFlowCallable extends DotNet:: Callable {
251
- DataFlowCallable ( ) { this .isUnboundDeclaration ( ) }
249
+ /** A callable used for data flow. */
250
+ class DataFlowCallable extends TDataFlowCallable {
251
+ /** Get the underlying source code callable, if any. */
252
+ DotNet:: Callable asCallable ( ) { this = TDotNetCallable ( result ) }
253
+
254
+ /** Get the underlying summarized callable, if any. */
255
+ FlowSummary:: SummarizedCallable asSummarizedCallable ( ) { this = TSummarizedCallable ( result ) }
256
+
257
+ /** Get the underlying callable. */
258
+ DotNet:: Callable getUnderlyingCallable ( ) {
259
+ result = this .asCallable ( ) or result = this .asSummarizedCallable ( )
260
+ }
261
+
262
+ /** Gets a textual representation of this dataflow callable. */
263
+ string toString ( ) { result = this .getUnderlyingCallable ( ) .toString ( ) }
264
+
265
+ /** Get the location of this dataflow callable. */
266
+ Location getLocation ( ) { result = this .getUnderlyingCallable ( ) .getLocation ( ) }
252
267
}
253
268
254
269
/** A call relevant for data flow. */
@@ -306,18 +321,32 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
306
321
DispatchCall getDispatchCall ( ) { result = dc }
307
322
308
323
override DataFlowCallable getARuntimeTarget ( ) {
309
- result = getCallableForDataFlow ( dc .getADynamicTarget ( ) )
324
+ result .asCallable ( ) = getCallableForDataFlow ( dc .getADynamicTarget ( ) )
325
+ or
326
+ exists ( Callable c , boolean static |
327
+ result .asSummarizedCallable ( ) = c and
328
+ c = this .getATarget ( static )
329
+ |
330
+ static = false
331
+ or
332
+ static = true and not c instanceof RuntimeCallable
333
+ )
334
+ }
335
+
336
+ /** Gets a static or dynamic target of this call. */
337
+ Callable getATarget ( boolean static ) {
338
+ result = dc .getADynamicTarget ( ) .getUnboundDeclaration ( ) and static = false
310
339
or
311
- result = dc .getAStaticTarget ( ) .getUnboundDeclaration ( ) and
312
- summarizedCallable ( result ) and
313
- not result instanceof RuntimeCallable
340
+ result = dc .getAStaticTarget ( ) .getUnboundDeclaration ( ) and static = true
314
341
}
315
342
316
343
override ControlFlow:: Nodes:: ElementNode getControlFlowNode ( ) { result = cfn }
317
344
318
345
override DataFlow:: ExprNode getNode ( ) { result .getControlFlowNode ( ) = cfn }
319
346
320
- override DataFlowCallable getEnclosingCallable ( ) { result = cfn .getEnclosingCallable ( ) }
347
+ override DataFlowCallable getEnclosingCallable ( ) {
348
+ result .getUnderlyingCallable ( ) = cfn .getEnclosingCallable ( )
349
+ }
321
350
322
351
override string toString ( ) { result = cfn .toString ( ) }
323
352
@@ -345,7 +374,9 @@ class ExplicitDelegateLikeDataFlowCall extends DelegateDataFlowCall, TExplicitDe
345
374
346
375
override DataFlow:: ExprNode getNode ( ) { result .getControlFlowNode ( ) = cfn }
347
376
348
- override DataFlowCallable getEnclosingCallable ( ) { result = cfn .getEnclosingCallable ( ) }
377
+ override DataFlowCallable getEnclosingCallable ( ) {
378
+ result .getUnderlyingCallable ( ) = cfn .getEnclosingCallable ( )
379
+ }
349
380
350
381
override string toString ( ) { result = cfn .toString ( ) }
351
382
@@ -363,13 +394,15 @@ class TransitiveCapturedDataFlowCall extends DataFlowCall, TTransitiveCapturedCa
363
394
364
395
TransitiveCapturedDataFlowCall ( ) { this = TTransitiveCapturedCall ( cfn , target ) }
365
396
366
- override DataFlowCallable getARuntimeTarget ( ) { result = target }
397
+ override DataFlowCallable getARuntimeTarget ( ) { result . getUnderlyingCallable ( ) = target }
367
398
368
399
override ControlFlow:: Nodes:: ElementNode getControlFlowNode ( ) { result = cfn }
369
400
370
401
override DataFlow:: ExprNode getNode ( ) { none ( ) }
371
402
372
- override DataFlowCallable getEnclosingCallable ( ) { result = cfn .getEnclosingCallable ( ) }
403
+ override DataFlowCallable getEnclosingCallable ( ) {
404
+ result .getUnderlyingCallable ( ) = cfn .getEnclosingCallable ( )
405
+ }
373
406
374
407
override string toString ( ) { result = "[transitive] " + cfn .toString ( ) }
375
408
@@ -384,14 +417,16 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
384
417
385
418
override DataFlowCallable getARuntimeTarget ( ) {
386
419
// There is no dispatch library for CIL, so do not consider overrides for now
387
- result = getCallableForDataFlow ( call .getTarget ( ) )
420
+ result . getUnderlyingCallable ( ) = getCallableForDataFlow ( call .getTarget ( ) )
388
421
}
389
422
390
423
override ControlFlow:: Nodes:: ElementNode getControlFlowNode ( ) { none ( ) }
391
424
392
425
override DataFlow:: ExprNode getNode ( ) { result .getExpr ( ) = call }
393
426
394
- override DataFlowCallable getEnclosingCallable ( ) { result = call .getEnclosingCallable ( ) }
427
+ override DataFlowCallable getEnclosingCallable ( ) {
428
+ result .getUnderlyingCallable ( ) = call .getEnclosingCallable ( )
429
+ }
395
430
396
431
override string toString ( ) { result = call .toString ( ) }
397
432
@@ -406,7 +441,7 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
406
441
* the method `Select`.
407
442
*/
408
443
class SummaryCall extends DelegateDataFlowCall , TSummaryCall {
409
- private FlowSummary :: SummarizedCallable c ;
444
+ private FlowSummaryImpl :: Public :: SummarizedCallable c ;
410
445
private Node receiver ;
411
446
412
447
SummaryCall ( ) { this = TSummaryCall ( c , receiver ) }
0 commit comments