@@ -794,6 +794,9 @@ private module Stage2 {
794794
795795 class CcCall extends Cc {
796796 CcCall ( ) { this = true }
797+
798+ /** Holds if this call context may be `call`. */
799+ predicate matchesCall ( DataFlowCall call ) { any ( ) }
797800 }
798801
799802 class CcNoCall extends Cc {
@@ -834,6 +837,9 @@ private module Stage2 {
834837
835838 private predicate flowIntoCall = flowIntoCallNodeCand1 / 5 ;
836839
840+ bindingset [ ap, contentType]
841+ private predicate typecheckStore ( Ap ap , DataFlowType contentType ) { any ( ) }
842+
837843 /* Begin: Stage 2 logic. */
838844 private predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
839845 PrevStage:: revFlow ( node , _, _, apa , config )
@@ -847,7 +853,8 @@ private module Stage2 {
847853 * argument in a call, and if so, `argAp` records the access path of that
848854 * argument.
849855 */
850- private predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
856+ pragma [ nomagic]
857+ predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
851858 flowCand ( node , _, config ) and
852859 config .isSource ( node ) and
853860 cc = ccAny ( ) and
@@ -920,7 +927,8 @@ private module Stage2 {
920927 ) {
921928 exists ( DataFlowType contentType |
922929 fwdFlow ( node1 , cc , argAp , ap1 , config ) and
923- PrevStage:: storeStepCand ( node1 , getApprox ( ap1 ) , tc , node2 , contentType , config )
930+ PrevStage:: storeStepCand ( node1 , getApprox ( ap1 ) , tc , node2 , contentType , config ) and
931+ typecheckStore ( ap1 , contentType )
924932 )
925933 }
926934
@@ -1154,7 +1162,8 @@ private module Stage2 {
11541162 ) {
11551163 exists ( ReturnNodeExt ret , CcCall ccc |
11561164 revFlowOut ( call , ret , toReturn , returnAp , ap , config ) and
1157- fwdFlow ( ret , ccc , apSome ( _) , ap , config )
1165+ fwdFlow ( ret , ccc , apSome ( _) , ap , config ) and
1166+ ccc .matchesCall ( call )
11581167 )
11591168 }
11601169
@@ -1391,6 +1400,9 @@ private module Stage3 {
13911400
13921401 class CcCall extends Cc {
13931402 CcCall ( ) { this = true }
1403+
1404+ /** Holds if this call context may be `call`. */
1405+ predicate matchesCall ( DataFlowCall call ) { any ( ) }
13941406 }
13951407
13961408 class CcNoCall extends Cc {
@@ -1423,6 +1435,19 @@ private module Stage3 {
14231435
14241436 private predicate flowIntoCall = flowIntoCallNodeCand2 / 5 ;
14251437
1438+ bindingset [ node, ap]
1439+ private predicate filter ( Node node , Ap ap ) {
1440+ not ap .isClearedAt ( node ) and
1441+ if node instanceof CastingNode then compatibleTypes ( getNodeType ( node ) , ap .getType ( ) ) else any ( )
1442+ }
1443+
1444+ bindingset [ ap, contentType]
1445+ private predicate typecheckStore ( Ap ap , DataFlowType contentType ) {
1446+ // We need to typecheck stores here, since reverse flow through a getter
1447+ // might have a different type here compared to inside the getter.
1448+ compatibleTypes ( ap .getType ( ) , contentType )
1449+ }
1450+
14261451 /* Begin: Stage 3 logic. */
14271452 private predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
14281453 PrevStage:: revFlow ( node , _, _, apa , config )
@@ -1440,13 +1465,12 @@ private module Stage3 {
14401465 predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
14411466 fwdFlow0 ( node , cc , argAp , ap , config ) and
14421467 flowCand ( node , unbindBool ( getApprox ( ap ) ) , config ) and
1443- not ap .isClearedAt ( node ) and
1444- if node instanceof CastingNode then compatibleTypes ( getNodeType ( node ) , ap .getType ( ) ) else any ( )
1468+ filter ( node , ap )
14451469 }
14461470
14471471 pragma [ nomagic]
14481472 private predicate fwdFlow0 ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
1449- flowCand ( node , false , config ) and
1473+ flowCand ( node , _ , config ) and
14501474 config .isSource ( node ) and
14511475 cc = ccAny ( ) and
14521476 argAp = apNone ( ) and
@@ -1519,9 +1543,7 @@ private module Stage3 {
15191543 exists ( DataFlowType contentType |
15201544 fwdFlow ( node1 , cc , argAp , ap1 , config ) and
15211545 PrevStage:: storeStepCand ( node1 , getApprox ( ap1 ) , tc , node2 , contentType , config ) and
1522- // We need to typecheck stores here, since reverse flow through a getter
1523- // might have a different type here compared to inside the getter.
1524- compatibleTypes ( ap1 .getType ( ) , contentType )
1546+ typecheckStore ( ap1 , contentType )
15251547 )
15261548 }
15271549
@@ -1749,7 +1771,8 @@ private module Stage3 {
17491771 ) {
17501772 exists ( ReturnNodeExt ret , CcCall ccc |
17511773 revFlowOut ( call , ret , toReturn , returnAp , ap , config ) and
1752- fwdFlow ( ret , ccc , apSome ( _) , ap , config )
1774+ fwdFlow ( ret , ccc , apSome ( _) , ap , config ) and
1775+ ccc .matchesCall ( call )
17531776 )
17541777 }
17551778
@@ -1772,6 +1795,8 @@ private module Stage3 {
17721795 )
17731796 }
17741797
1798+ predicate revFlow ( Node node , Configuration config ) { revFlow ( node , _, _, _, config ) }
1799+
17751800 private predicate fwdConsCand ( TypedContent tc , Ap ap , Configuration config ) {
17761801 storeStepFwd ( _, ap , tc , _, _, config )
17771802 }
@@ -2105,6 +2130,12 @@ private module Stage4 {
21052130 PrevStage:: revFlow ( node1 , _, _, _, unbind ( config ) )
21062131 }
21072132
2133+ bindingset [ node, ap]
2134+ private predicate filter ( Node node , Ap ap ) { any ( ) }
2135+
2136+ bindingset [ ap, contentType]
2137+ private predicate typecheckStore ( Ap ap , DataFlowType contentType ) { any ( ) }
2138+
21082139 /* Begin: Stage 4 logic. */
21092140 private predicate flowCand ( Node node , ApApprox apa , Configuration config ) {
21102141 PrevStage:: revFlow ( node , _, _, apa , config )
@@ -2118,11 +2149,14 @@ private module Stage4 {
21182149 * argument in a call, and if so, `argAp` records the access path of that
21192150 * argument.
21202151 */
2152+ pragma [ nomagic]
21212153 predicate fwdFlow ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
21222154 fwdFlow0 ( node , cc , argAp , ap , config ) and
2123- flowCand ( node , getApprox ( ap ) , config )
2155+ flowCand ( node , getApprox ( ap ) , config ) and
2156+ filter ( node , ap )
21242157 }
21252158
2159+ pragma [ nomagic]
21262160 private predicate fwdFlow0 ( Node node , Cc cc , ApOption argAp , Ap ap , Configuration config ) {
21272161 flowCand ( node , _, config ) and
21282162 config .isSource ( node ) and
@@ -2196,7 +2230,8 @@ private module Stage4 {
21962230 ) {
21972231 exists ( DataFlowType contentType |
21982232 fwdFlow ( node1 , cc , argAp , ap1 , config ) and
2199- PrevStage:: storeStepCand ( node1 , getApprox ( ap1 ) , tc , node2 , contentType , config )
2233+ PrevStage:: storeStepCand ( node1 , getApprox ( ap1 ) , tc , node2 , contentType , config ) and
2234+ typecheckStore ( ap1 , contentType )
22002235 )
22012236 }
22022237
@@ -2448,7 +2483,7 @@ private module Stage4 {
24482483 )
24492484 }
24502485
2451- predicate revFlow ( Node n , Configuration config ) { revFlow ( n , _, _, _, config ) }
2486+ predicate revFlow ( Node node , Configuration config ) { revFlow ( node , _, _, _, config ) }
24522487
24532488 private predicate fwdConsCand ( TypedContent tc , Ap ap , Configuration config ) {
24542489 storeStepFwd ( _, ap , tc , _, _, config )
0 commit comments