@@ -98,9 +98,17 @@ module API {
98
98
/**
99
99
* Gets a node representing the result of calling a method on the receiver represented by this node.
100
100
*/
101
- Node getReturn ( string method ) {
102
- result = this .getASubclass ( ) .getASuccessor ( Label:: return ( method ) )
103
- }
101
+ Node getMethod ( string method ) { result = this .getASubclass ( ) .getASuccessor ( Label:: method ( method ) ) }
102
+
103
+ /**
104
+ * Gets a node representing the result of this call.
105
+ */
106
+ Node getReturn ( ) { result = this .getASuccessor ( Label:: return ( ) ) }
107
+
108
+ /**
109
+ * Gets a node representing the result of calling a method on the receiver represented by this node.
110
+ */
111
+ Node getReturn ( string method ) { result = this .getMethod ( method ) .getReturn ( ) }
104
112
105
113
private predicate hasParameterIndex ( int n ) {
106
114
exists ( string str |
@@ -288,6 +296,8 @@ module API {
288
296
newtype TApiNode =
289
297
/** The root of the API graph. */
290
298
MkRoot ( ) or
299
+ /** The method accessed at `call`, synthetically treated as a separate object. */
300
+ MkMethodCall ( DataFlow:: CallNode call ) { isUse ( call ) } or
291
301
/** A use of an API member at the node `nd`. */
292
302
MkUse ( DataFlow:: Node nd ) { isUse ( nd ) } or
293
303
/** A value that escapes into an API at the node `nd` */
@@ -332,14 +342,7 @@ module API {
332
342
ref .asExpr ( ) = c and
333
343
read = c .getExpr ( )
334
344
)
335
- or
336
- // Calling a method on a node that is a use of `base`
337
- exists ( ExprNodes:: MethodCallCfgNode call , string name |
338
- node .asExpr ( ) = call .getReceiver ( ) and
339
- name = call .getExpr ( ) .getMethodName ( ) and
340
- lbl = Label:: return ( name ) and
341
- ref .asExpr ( ) = call
342
- )
345
+ // note: method calls are not handled here as there is no DataFlow::Node for the intermediate MkMethodCall API node
343
346
}
344
347
345
348
pragma [ nomagic]
@@ -351,6 +354,8 @@ module API {
351
354
useStep ( _, node , nd )
352
355
)
353
356
or
357
+ useCandFwd ( ) .flowsTo ( nd .( DataFlow:: CallNode ) .getReceiver ( ) )
358
+ or
354
359
parameterStep ( _, defCand ( ) , nd )
355
360
}
356
361
@@ -395,10 +400,8 @@ module API {
395
400
}
396
401
397
402
private predicate isDef ( DataFlow:: Node rhs ) {
398
- exists ( DataFlow:: Node use |
399
- useCandFwd ( ) .flowsTo ( use ) and
400
- argumentStep ( _, use , rhs )
401
- )
403
+ // If a call node is relevant as a use-node, treat its arguments as def-nodes
404
+ argumentStep ( _, useCandFwd ( ) , rhs )
402
405
}
403
406
404
407
/** Gets a data flow node that flows to the RHS of a def-node. */
@@ -504,6 +507,11 @@ module API {
504
507
result = trackDefNode ( rhs , TypeBackTracker:: end ( ) )
505
508
}
506
509
510
+ pragma [ nomagic]
511
+ private predicate useNodeReachesReceiver ( DataFlow:: Node use , DataFlow:: CallNode call ) {
512
+ trackUseNode ( use ) .flowsTo ( call .getReceiver ( ) )
513
+ }
514
+
507
515
/**
508
516
* Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
509
517
*/
@@ -519,6 +527,11 @@ module API {
519
527
trackUseNode ( src ) .flowsTo ( node ) and
520
528
useStep ( lbl , node , ref )
521
529
)
530
+ or
531
+ exists ( DataFlow:: Node callback |
532
+ pred = MkDef ( callback ) and
533
+ parameterStep ( lbl , trackDefNode ( callback ) , ref )
534
+ )
522
535
)
523
536
or
524
537
// `pred` is a use of class A
@@ -532,15 +545,26 @@ module API {
532
545
lbl = Label:: subclass ( )
533
546
)
534
547
or
535
- exists ( DataFlow:: Node use , DataFlow:: Node base , DataFlow:: Node rhs |
536
- pred = MkUse ( use ) and
537
- trackUseNode ( use ) .flowsTo ( base ) and
538
- argumentStep ( lbl , base , rhs ) and
539
- succ = MkDef ( rhs )
548
+ exists ( DataFlow:: CallNode call |
549
+ // from receiver to method call node
550
+ exists ( DataFlow:: Node receiver |
551
+ pred = MkUse ( receiver ) and
552
+ useNodeReachesReceiver ( receiver , call ) and
553
+ lbl = Label:: method ( call .getMethodName ( ) ) and
554
+ succ = MkMethodCall ( call )
555
+ )
540
556
or
541
- pred = MkDef ( rhs ) and
542
- parameterStep ( lbl , trackDefNode ( rhs ) , use ) and
543
- succ = MkUse ( use )
557
+ // from method call node to return and arguments
558
+ pred = MkMethodCall ( call ) and
559
+ (
560
+ lbl = Label:: return ( ) and
561
+ succ = MkUse ( call )
562
+ or
563
+ exists ( DataFlow:: Node rhs |
564
+ argumentStep ( lbl , call , rhs ) and
565
+ succ = MkDef ( rhs )
566
+ )
567
+ )
544
568
)
545
569
}
546
570
@@ -564,10 +588,13 @@ private module Label {
564
588
/** Gets the `member` edge label for the unknown member. */
565
589
string unknownMember ( ) { result = "getUnknownMember()" }
566
590
567
- /** Gets the `return ` edge label. */
591
+ /** Gets the `method ` edge label. */
568
592
bindingset [ m]
569
593
bindingset [ result ]
570
- string return ( string m ) { result = "getReturn(\"" + m + "\")" }
594
+ string method ( string m ) { result = "getMethod(\"" + m + "\")" }
595
+
596
+ /** Gets the `return` edge label. */
597
+ string return ( ) { result = "getReturn()" }
571
598
572
599
string subclass ( ) { result = "getASubclass()" }
573
600
0 commit comments