@@ -115,6 +115,37 @@ class Portal extends TPortal {
115115 abstract int depth ( ) ;
116116}
117117
118+ /**
119+ * Gets an exit node for the specified portal, using TypeTracking.
120+ *
121+ * Called in instances where an exit node is computed from another exit node
122+ * (for example, in MemberPortal's portalBaseRef predicate).
123+ */
124+ private DataFlow:: SourceNode trackExitNode (
125+ Portal base , boolean isRemote , DataFlow:: TypeTracker t
126+ ) {
127+ t .start ( ) and
128+ result = base .getAnExitNode ( isRemote )
129+ or
130+ exists ( DataFlow:: TypeTracker t2 | result = trackExitNode ( base , isRemote , t2 ) .track ( t2 , t ) )
131+ }
132+
133+ /**
134+ * Gets an entry node for the specified portal, using TypeBackTracking.
135+ *
136+ * Parallel to trackExitNode above.
137+ */
138+ private DataFlow:: SourceNode trackEntryNode (
139+ Portal base , boolean escapes , DataFlow:: TypeBackTracker t
140+ ) {
141+ t .start ( ) and
142+ result = base .getAnEntryNode ( escapes ) .getALocalSource ( )
143+ or
144+ exists ( DataFlow:: TypeBackTracker t2 |
145+ result = trackEntryNode ( base , escapes , t2 ) .backtrack ( t2 , t )
146+ )
147+ }
148+
118149/**
119150 * A portal representing the exports value of the main module of an npm
120151 * package (that is, a value of `module.exports` for CommonJS modules, or
@@ -260,9 +291,9 @@ private class MemberPortal extends CompoundPortal, MkMemberPortal {
260291private module MemberPortal {
261292 /** Gets a node representing a value flowing through `base`, that is, either an entry node or an exit node. */
262293 private DataFlow:: SourceNode portalBaseRef ( Portal base , boolean escapes ) {
263- result = base . getAnExitNode ( escapes )
294+ result = trackExitNode ( base , escapes , DataFlow :: TypeTracker :: end ( ) )
264295 or
265- result = base . getAnEntryNode ( escapes ) . getALocalSource ( )
296+ result = trackEntryNode ( base , escapes , DataFlow :: TypeBackTracker :: end ( ) )
266297 }
267298
268299 /** Holds if `read` is a read of property `prop` of a value flowing through `base`. */
@@ -342,13 +373,13 @@ private module InstancePortal {
342373 Portal base , DataFlow:: SourceNode ctor , AbstractInstance i , boolean escapes
343374 ) {
344375 ctor = DataFlow:: valueNode ( i .getConstructor ( ) .getDefinition ( ) ) and
345- ctor . flowsTo ( base . getAnEntryNode ( escapes ) ) and
376+ ctor = trackEntryNode ( base , escapes , DataFlow :: TypeBackTracker :: end ( ) ) and
346377 instantiable ( ctor )
347378 }
348379
349380 /** Holds if `nd` is an expression evaluating to an instance of `base`. */
350381 predicate instanceUse ( Portal base , DataFlow:: SourceNode nd , boolean isRemote ) {
351- nd = base . getAnExitNode ( isRemote ) .getAnInstantiation ( )
382+ nd = trackExitNode ( base , isRemote , DataFlow :: TypeTracker :: end ( ) ) .getAnInstantiation ( )
352383 or
353384 isInstance ( base , _, nd .analyze ( ) .getAValue ( ) , isRemote )
354385 }
@@ -415,13 +446,14 @@ class ParameterPortal extends CompoundPortal, MkParameterPortal {
415446private module ParameterPortal {
416447 /** Holds if `param` is the `i`th parameter of a function flowing through `base`. */
417448 predicate parameter ( Portal base , int i , DataFlow:: SourceNode param , boolean isRemote ) {
418- param = base .getAnEntryNode ( isRemote ) .getALocalSource ( ) .( DataFlow:: FunctionNode ) .getParameter ( i )
449+ param = trackEntryNode ( base , isRemote , DataFlow:: TypeBackTracker:: end ( ) ) .( DataFlow:: FunctionNode )
450+ .getParameter ( i )
419451 }
420452
421453 /** Holds if `arg` is the `i`th argument passed to an invocation of a function flowing through `base`. */
422454 predicate argument ( Portal base , int i , DataFlow:: Node arg , boolean escapes ) {
423455 exists ( DataFlow:: InvokeNode invk |
424- invk = base . getAnExitNode ( escapes ) .getAnInvocation ( ) and
456+ invk = trackExitNode ( base , escapes , DataFlow :: TypeTracker :: end ( ) ) .getAnInvocation ( ) and
425457 arg = invk .getArgument ( i )
426458 )
427459 }
@@ -449,11 +481,14 @@ class ReturnPortal extends CompoundPortal, MkReturnPortal {
449481private module ReturnPortal {
450482 /** Holds if `invk` is a call to a function flowing through `callee`. */
451483 predicate calls ( DataFlow:: InvokeNode invk , Portal callee , boolean isRemote ) {
452- invk = callee .getAnExitNode ( isRemote ) .getAnInvocation ( )
484+ invk = trackExitNode ( callee , isRemote , DataFlow:: TypeTracker:: end ( ) )
485+ .getAnInvocation ( )
453486 }
454487
455488 /** Holds if `ret` is a return node of a function flowing through `callee`. */
456489 predicate returns ( Portal base , DataFlow:: Node ret , boolean escapes ) {
457- ret = base .getAnEntryNode ( escapes ) .getALocalSource ( ) .( DataFlow:: FunctionNode ) .getAReturn ( )
490+ ret = trackEntryNode ( base , escapes , DataFlow:: TypeBackTracker:: end ( ) )
491+ .( DataFlow:: FunctionNode )
492+ .getAReturn ( )
458493 }
459494}
0 commit comments