@@ -766,6 +766,10 @@ private module Stage2 {
766766
767767 Cc ccAny ( ) { result = false }
768768
769+ predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
770+ Stage1:: revFlow ( node , config ) and exists ( apa )
771+ }
772+
769773 /* Begin: Stage 2 logic. */
770774 /**
771775 * Holds if `node` is reachable from a source in the configuration `config`.
@@ -777,13 +781,13 @@ private module Stage2 {
777781 * value was stored into a field of the argument.
778782 */
779783 private predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
780- Stage1 :: revFlow ( node , config ) and
784+ flowCand ( node , _ , config ) and
781785 config .isSource ( node ) and
782786 cc = ccAny ( ) and
783787 argAp = apNone ( ) and
784788 ap = getApNil ( node )
785789 or
786- Stage1 :: revFlow ( node , unbind ( config ) ) and
790+ flowCand ( node , _ , unbind ( config ) ) and
787791 (
788792 exists ( Node mid |
789793 fwdFlow ( mid , cc , argAp , ap , config ) and
@@ -1265,6 +1269,9 @@ private module Stage3 {
12651269
12661270 class ApNil = AccessPathFrontNil ;
12671271
1272+ bindingset [ result , ap]
1273+ ApApprox getApprox ( Ap ap ) { result = unbindBool ( ap .toBoolNonEmpty ( ) ) }
1274+
12681275 ApNil getApNil ( Node node ) { result = TFrontNil ( getNodeType ( node ) ) }
12691276
12701277 bindingset [ tc, tail]
@@ -1283,6 +1290,10 @@ private module Stage3 {
12831290
12841291 Cc ccAny ( ) { result = false }
12851292
1293+ predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
1294+ Stage2:: revFlow ( node , _, _, apa , config )
1295+ }
1296+
12861297 /* Begin: Stage 3 logic. */
12871298 /**
12881299 * Holds if `node` is reachable with access path front `ap` from a
@@ -1295,13 +1306,14 @@ private module Stage3 {
12951306 pragma [ nomagic]
12961307 predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
12971308 fwdFlow0 ( node , cc , argAp , ap , config ) and
1309+ flowCand ( node , getApprox ( ap ) , config ) and
12981310 not ap .isClearedAt ( node ) and
12991311 if node instanceof CastingNode then compatibleTypes ( getNodeType ( node ) , ap .getType ( ) ) else any ( )
13001312 }
13011313
13021314 pragma [ nomagic]
13031315 private predicate fwdFlow0 ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
1304- Stage2 :: revFlow ( node , _ , _ , false , config ) and
1316+ flowCand ( node , false , config ) and
13051317 config .isSource ( node ) and
13061318 cc = ccAny ( ) and
13071319 argAp = apNone ( ) and
@@ -1319,15 +1331,15 @@ private module Stage3 {
13191331 or
13201332 exists ( Node mid |
13211333 fwdFlow ( mid , _, _, ap , config ) and
1322- Stage2 :: revFlow ( node , unbind ( config ) ) and
1334+ flowCand ( node , _ , unbind ( config ) ) and
13231335 jumpStep ( mid , node , config ) and
13241336 cc = ccAny ( ) and
13251337 argAp = apNone ( )
13261338 )
13271339 or
13281340 exists ( Node mid , ApNil nil |
13291341 fwdFlow ( mid , _, _, nil , config ) and
1330- Stage2 :: revFlow ( node , unbind ( config ) ) and
1342+ flowCand ( node , _ , unbind ( config ) ) and
13311343 additionalJumpStep ( mid , node , config ) and
13321344 cc = ccAny ( ) and
13331345 argAp = apNone ( ) and
@@ -1344,7 +1356,7 @@ private module Stage3 {
13441356 exists ( Ap ap0 , Content c |
13451357 fwdFlowRead ( ap0 , c , _, node , cc , argAp , config ) and
13461358 fwdFlowConsCand ( ap0 , c , ap , config ) and
1347- Stage2 :: revFlow ( node , _ , _ , unbindBool ( ap .toBoolNonEmpty ( ) ) , unbind ( config ) )
1359+ flowCand ( node , unbindBool ( ap .toBoolNonEmpty ( ) ) , unbind ( config ) )
13481360 )
13491361 or
13501362 // flow into a callable
@@ -1827,6 +1839,8 @@ private module Stage4 {
18271839
18281840 class ApNil = AccessPathApproxNil ;
18291841
1842+ ApApprox getApprox ( Ap ap ) { result = ap .getFront ( ) }
1843+
18301844 ApNil getApNil ( Node node ) { result = TNil ( getNodeType ( node ) ) }
18311845
18321846 bindingset [ tc, tail]
@@ -1845,6 +1859,10 @@ private module Stage4 {
18451859
18461860 Cc ccAny ( ) { result instanceof CallContextAny }
18471861
1862+ predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
1863+ Stage3:: revFlow ( node , _, _, apa , config )
1864+ }
1865+
18481866 /* Begin: Stage 4 logic. */
18491867 /**
18501868 * Holds if `node` is reachable with approximate access path `ap` from a source
@@ -1856,17 +1874,17 @@ private module Stage4 {
18561874 */
18571875 predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
18581876 fwdFlow0 ( node , cc , argAp , ap , config ) and
1859- Stage3 :: revFlow ( node , _ , _ , ap . getFront ( ) , config )
1877+ flowCand ( node , getApprox ( ap ) , config )
18601878 }
18611879
18621880 private predicate fwdFlow0 ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
1863- Stage3 :: revFlow ( node , _ , _ , _, config ) and
1881+ flowCand ( node , _, config ) and
18641882 config .isSource ( node ) and
18651883 cc = ccAny ( ) and
18661884 argAp = apNone ( ) and
18671885 ap = getApNil ( node )
18681886 or
1869- Stage3 :: revFlow ( node , _ , _ , _, unbind ( config ) ) and
1887+ flowCand ( node , _, unbind ( config ) ) and
18701888 (
18711889 exists ( Node mid , LocalCallContext localCC |
18721890 fwdFlowLocalEntry ( mid , cc , argAp , ap , localCC , config ) and
@@ -1962,7 +1980,7 @@ private module Stage4 {
19621980 Configuration config
19631981 ) {
19641982 storeCand2 ( mid , tc , node , _, config ) and
1965- Stage3 :: revFlow ( mid , _ , _ , apf0 , config ) and
1983+ flowCand ( mid , apf0 , config ) and
19661984 apf .headUsesContent ( tc )
19671985 }
19681986
@@ -1973,7 +1991,7 @@ private module Stage4 {
19731991 exists ( AccessPathFront apf |
19741992 storeCand ( mid , tc , node , apf0 , apf , config ) and
19751993 stage3consCand ( tc , apf0 , config ) and
1976- Stage3 :: revFlow ( node , _ , _ , apf , unbind ( config ) )
1994+ flowCand ( node , apf , unbind ( config ) )
19771995 )
19781996 }
19791997
@@ -1996,7 +2014,7 @@ private module Stage4 {
19962014 flowIntoCallNodeCand2 ( call , arg , p , allowsFieldFlow , config ) and
19972015 c = p .getEnclosingCallable ( ) and
19982016 c = resolveCall ( call , outercc ) and
1999- Stage3 :: revFlow ( p , _ , _ , _, unbind ( config ) ) and
2017+ flowCand ( p , _, unbind ( config ) ) and
20002018 if recordDataFlowCallSite ( call , c )
20012019 then innercc = TSpecificCall ( call )
20022020 else innercc = TSomeCall ( )
@@ -2014,7 +2032,7 @@ private module Stage4 {
20142032 fwdFlow ( ret , innercc , argAp , ap , config ) and
20152033 flowOutOfCallNodeCand2 ( call , ret , node , allowsFieldFlow , config ) and
20162034 innerc = ret .getEnclosingCallable ( ) and
2017- Stage3 :: revFlow ( node , _ , _ , _, unbind ( config ) ) and
2035+ flowCand ( node , _, unbind ( config ) ) and
20182036 (
20192037 resolveReturn ( innercc , innerc , call )
20202038 or
0 commit comments