@@ -207,7 +207,7 @@ module API {
207207 this = Impl:: MkUse ( result ) or
208208 this = Impl:: MkDef ( result ) or
209209 this = Impl:: MkAsyncFuncResult ( result ) or
210- this = Impl:: MkSyntheticCallbackArg ( _, result )
210+ this = Impl:: MkSyntheticCallbackArg ( _, _ , result )
211211 }
212212
213213 /**
@@ -391,8 +391,8 @@ module API {
391391 not n .isRoot ( ) and
392392 isUsed ( n )
393393 } or
394- MkSyntheticCallbackArg ( DataFlow:: Node src , DataFlow:: InvokeNode nd ) {
395- trackUseNode ( src , true ) .flowsTo ( nd .getCalleeNode ( ) )
394+ MkSyntheticCallbackArg ( DataFlow:: Node src , int bound , DataFlow:: InvokeNode nd ) {
395+ trackUseNode ( src , true , bound ) .flowsTo ( nd .getCalleeNode ( ) )
396396 }
397397
398398 class TDef = MkModuleDef or TNonModuleDef ;
@@ -528,18 +528,20 @@ module API {
528528 * The receiver is considered to be argument -1.
529529 */
530530 private predicate argumentPassing ( TApiNode base , int i , DataFlow:: Node arg ) {
531- exists ( DataFlow:: Node use , DataFlow:: SourceNode pred |
532- use ( base , use ) and pred = trackUseNode ( use , _)
531+ exists ( DataFlow:: Node use , DataFlow:: SourceNode pred , int bound |
532+ use ( base , use ) and pred = trackUseNode ( use , _, bound )
533533 |
534- arg = pred .getAnInvocation ( ) .getArgument ( i )
534+ arg = pred .getAnInvocation ( ) .getArgument ( i - bound )
535535 or
536536 arg = pred .getACall ( ) .getReceiver ( ) and
537+ bound = 0 and
537538 i = - 1
538539 or
539540 exists ( DataFlow:: PartialInvokeNode pin , DataFlow:: Node callback | pred .flowsTo ( callback ) |
540- pin .isPartialArgument ( callback , arg , i )
541+ pin .isPartialArgument ( callback , arg , i - bound )
541542 or
542543 arg = pin .getBoundReceiver ( callback ) and
544+ bound = 0 and
543545 i = - 1
544546 )
545547 )
@@ -616,7 +618,7 @@ module API {
616618 )
617619 or
618620 exists ( DataFlow:: InvokeNode call |
619- base = MkSyntheticCallbackArg ( _, call ) and
621+ base = MkSyntheticCallbackArg ( _, _ , call ) and
620622 lbl = Label:: parameter ( 1 ) and
621623 ref = awaited ( call )
622624 )
@@ -683,34 +685,55 @@ module API {
683685 )
684686 }
685687
688+ /**
689+ * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows.
690+ *
691+ * The flow from `nd` to that node may be inter-procedural. If `promisified` is `true`, the
692+ * flow goes through a promisification, and `boundArgs` indicates how many arguments have been
693+ * bound throughout the flow. (To ensure termination, we somewhat arbitrarily constrain the
694+ * number of bound arguments to be at most ten.)
695+ */
686696 private DataFlow:: SourceNode trackUseNode (
687- DataFlow:: SourceNode nd , boolean promisified , DataFlow:: TypeTracker t
697+ DataFlow:: SourceNode nd , boolean promisified , int boundArgs , DataFlow:: TypeTracker t
688698 ) {
689699 t .start ( ) and
690700 use ( _, nd ) and
691701 result = nd and
692- promisified = false
702+ promisified = false and
703+ boundArgs = 0
693704 or
694705 exists ( DataFlow:: CallNode promisify |
695706 promisify = API:: moduleImport ( [ "util" , "bluebird" ] ) .getMember ( "promisify" ) .getACall ( )
696707 |
697- trackUseNode ( nd , false , t .continue ( ) ) .flowsTo ( promisify .getArgument ( 0 ) ) and
708+ trackUseNode ( nd , false , boundArgs , t .continue ( ) ) .flowsTo ( promisify .getArgument ( 0 ) ) and
698709 promisified = true and
699710 result = promisify
700711 )
701712 or
702- exists ( DataFlow:: TypeTracker t2 | result = trackUseNode ( nd , promisified , t2 ) .track ( t2 , t ) )
713+ exists ( DataFlow:: PartialInvokeNode pin , DataFlow:: Node pred , int predBoundArgs |
714+ trackUseNode ( nd , promisified , predBoundArgs , t .continue ( ) ) .flowsTo ( pred ) and
715+ result = pin .getBoundFunction ( pred , boundArgs - predBoundArgs ) and
716+ boundArgs <= 10
717+ )
718+ or
719+ exists ( DataFlow:: TypeTracker t2 |
720+ result = trackUseNode ( nd , promisified , boundArgs , t2 ) .track ( t2 , t )
721+ )
703722 }
704723
705- private DataFlow:: SourceNode trackUseNode ( DataFlow:: SourceNode nd , boolean promisified ) {
706- result = trackUseNode ( nd , promisified , DataFlow:: TypeTracker:: end ( ) )
724+ private DataFlow:: SourceNode trackUseNode (
725+ DataFlow:: SourceNode nd , boolean promisified , int boundArgs
726+ ) {
727+ result = trackUseNode ( nd , promisified , boundArgs , DataFlow:: TypeTracker:: end ( ) )
707728 }
708729
709730 /**
710731 * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node.
711732 */
712733 cached
713- DataFlow:: SourceNode trackUseNode ( DataFlow:: SourceNode nd ) { result = trackUseNode ( nd , false ) }
734+ DataFlow:: SourceNode trackUseNode ( DataFlow:: SourceNode nd ) {
735+ result = trackUseNode ( nd , false , 0 )
736+ }
714737
715738 private DataFlow:: SourceNode trackDefNode ( DataFlow:: Node nd , DataFlow:: TypeBackTracker t ) {
716739 t .start ( ) and
@@ -740,11 +763,14 @@ module API {
740763
741764 private DataFlow:: SourceNode awaited ( DataFlow:: InvokeNode call , DataFlow:: TypeTracker t ) {
742765 t .startInPromise ( ) and
743- exists ( MkSyntheticCallbackArg ( _, call ) )
766+ exists ( MkSyntheticCallbackArg ( _, _ , call ) )
744767 or
745768 exists ( DataFlow:: TypeTracker t2 | result = awaited ( call , t2 ) .track ( t2 , t ) )
746769 }
747770
771+ /**
772+ * Gets a node holding the resolved value of promise `call`.
773+ */
748774 private DataFlow:: Node awaited ( DataFlow:: InvokeNode call ) {
749775 result = awaited ( call , DataFlow:: TypeTracker:: end ( ) )
750776 }
@@ -810,10 +836,10 @@ module API {
810836 succ = MkAsyncFuncResult ( f )
811837 )
812838 or
813- exists ( DataFlow:: SourceNode src , DataFlow:: InvokeNode call |
839+ exists ( DataFlow:: SourceNode src , int bound , DataFlow:: InvokeNode call |
814840 use ( pred , src ) and
815- lbl = Label:: parameter ( call .getNumArgument ( ) ) and
816- succ = MkSyntheticCallbackArg ( src , call )
841+ lbl = Label:: parameter ( bound + call .getNumArgument ( ) ) and
842+ succ = MkSyntheticCallbackArg ( src , bound , call )
817843 )
818844 }
819845
0 commit comments