@@ -98,9 +98,17 @@ module API {
9898 /**
9999 * Gets a node representing the result of calling a method on the receiver represented by this node.
100100 */
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 ( ) }
104112
105113 private predicate hasParameterIndex ( int n ) {
106114 exists ( string str |
@@ -288,6 +296,8 @@ module API {
288296 newtype TApiNode =
289297 /** The root of the API graph. */
290298 MkRoot ( ) or
299+ /** The method accessed at `call`, synthetically treated as a separate object. */
300+ MkMethodCall ( DataFlow:: CallNode call ) { isUse ( call ) } or
291301 /** A use of an API member at the node `nd`. */
292302 MkUse ( DataFlow:: Node nd ) { isUse ( nd ) } or
293303 /** A value that escapes into an API at the node `nd` */
@@ -332,14 +342,7 @@ module API {
332342 ref .asExpr ( ) = c and
333343 read = c .getExpr ( )
334344 )
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
343346 }
344347
345348 pragma [ nomagic]
@@ -351,6 +354,8 @@ module API {
351354 useStep ( _, node , nd )
352355 )
353356 or
357+ useCandFwd ( ) .flowsTo ( nd .( DataFlow:: CallNode ) .getReceiver ( ) )
358+ or
354359 parameterStep ( _, defCand ( ) , nd )
355360 }
356361
@@ -395,10 +400,8 @@ module API {
395400 }
396401
397402 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 )
402405 }
403406
404407 /** Gets a data flow node that flows to the RHS of a def-node. */
@@ -504,6 +507,11 @@ module API {
504507 result = trackDefNode ( rhs , TypeBackTracker:: end ( ) )
505508 }
506509
510+ pragma [ nomagic]
511+ private predicate useNodeReachesReceiver ( DataFlow:: Node use , DataFlow:: CallNode call ) {
512+ trackUseNode ( use ) .flowsTo ( call .getReceiver ( ) )
513+ }
514+
507515 /**
508516 * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
509517 */
@@ -519,6 +527,11 @@ module API {
519527 trackUseNode ( src ) .flowsTo ( node ) and
520528 useStep ( lbl , node , ref )
521529 )
530+ or
531+ exists ( DataFlow:: Node callback |
532+ pred = MkDef ( callback ) and
533+ parameterStep ( lbl , trackDefNode ( callback ) , ref )
534+ )
522535 )
523536 or
524537 // `pred` is a use of class A
@@ -532,15 +545,26 @@ module API {
532545 lbl = Label:: subclass ( )
533546 )
534547 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+ )
540556 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+ )
544568 )
545569 }
546570
@@ -564,10 +588,13 @@ private module Label {
564588 /** Gets the `member` edge label for the unknown member. */
565589 string unknownMember ( ) { result = "getUnknownMember()" }
566590
567- /** Gets the `return ` edge label. */
591+ /** Gets the `method ` edge label. */
568592 bindingset [ m]
569593 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()" }
571598
572599 string subclass ( ) { result = "getASubclass()" }
573600
0 commit comments