@@ -613,11 +613,28 @@ private predicate hasSinkCallCtx(Configuration config) {
613613 * explicitly allowed
614614 */
615615bindingset [ p, kind]
616- private predicate parameterFlowThroughAllowed ( ParamNode p , ReturnKindExt kind ) {
616+ private predicate parameterFlowThroughAllowed ( ParamNodeEx p , ReturnKindExt kind ) {
617617 exists ( ParameterPosition pos | p .isParameterOf ( _, pos ) |
618618 not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
619619 or
620- allowParameterReturnInSelfCached ( p )
620+ allowParameterReturnInSelfCached ( p .asNode ( ) )
621+ )
622+ }
623+
624+ /**
625+ * Holds if flow from a parameter at position `pos` inside `c` to a return node of
626+ * kind `kind` is allowed.
627+ *
628+ * We don't expect a parameter to return stored in itself, unless
629+ * explicitly allowed
630+ */
631+ bindingset [ c, pos, kind]
632+ private predicate parameterFlowThroughAllowed (
633+ DataFlowCallable c , ParameterPosition pos , ReturnKindExt kind
634+ ) {
635+ exists ( ParamNodeEx p |
636+ p .isParameterOf ( c , pos ) and
637+ parameterFlowThroughAllowed ( p , kind )
621638 )
622639}
623640
@@ -1000,7 +1017,7 @@ private module Stage1 implements StageSig {
10001017 returnFlowCallableNodeCand ( c , kind , config ) and
10011018 p .getEnclosingCallable ( ) = c and
10021019 exists ( ap ) and
1003- parameterFlowThroughAllowed ( p . asNode ( ) , kind )
1020+ parameterFlowThroughAllowed ( p , kind )
10041021 )
10051022 }
10061023
@@ -1102,6 +1119,7 @@ private predicate flowIntoCallNodeCand1(
11021119 * edge in the graph of paths between sources and sinks that ignores call
11031120 * contexts.
11041121 */
1122+ pragma [ nomagic]
11051123private int branch ( NodeEx n1 , Configuration conf ) {
11061124 result =
11071125 strictcount ( NodeEx n |
@@ -1114,6 +1132,7 @@ private int branch(NodeEx n1, Configuration conf) {
11141132 * edge in the graph of paths between sources and sinks that ignores call
11151133 * contexts.
11161134 */
1135+ pragma [ nomagic]
11171136private int join ( NodeEx n2 , Configuration conf ) {
11181137 result =
11191138 strictcount ( NodeEx n |
@@ -1152,10 +1171,10 @@ pragma[nomagic]
11521171private predicate flowIntoCallNodeCand1 (
11531172 DataFlowCall call , ArgNodeEx arg , ParamNodeEx p , boolean allowsFieldFlow , Configuration config
11541173) {
1155- flowIntoCallNodeCand1 ( call , arg , p , config ) and
1174+ flowIntoCallNodeCand1 ( call , arg , p , pragma [ only_bind_into ] ( config ) ) and
11561175 exists ( int b , int j |
1157- b = branch ( arg , config ) and
1158- j = join ( p , config ) and
1176+ b = branch ( arg , pragma [ only_bind_into ] ( config ) ) and
1177+ j = join ( p , pragma [ only_bind_into ] ( config ) ) and
11591178 if b .minimum ( j ) <= config .fieldFlowBranchLimit ( )
11601179 then allowsFieldFlow = true
11611180 else allowsFieldFlow = false
@@ -1266,15 +1285,16 @@ private module MkStage<StageSig PrevStage> {
12661285
12671286 pragma [ nomagic]
12681287 private predicate flowThroughOutOfCall (
1269- DataFlowCall call , CcCall ccc , RetNodeEx ret , ReturnKindExt kind , NodeEx out ,
1270- boolean allowsFieldFlow , Configuration config
1288+ DataFlowCall call , DataFlowCallable c , CcCall ccc , RetNodeEx ret , ReturnKindExt kind ,
1289+ NodeEx out , boolean allowsFieldFlow , Configuration config
12711290 ) {
12721291 exists ( ReturnPosition pos |
12731292 flowOutOfCall ( call , ret , pos , out , allowsFieldFlow , pragma [ only_bind_into ] ( config ) ) and
12741293 kind = pos .getKind ( ) and
12751294 PrevStage:: callMayFlowThroughRev ( call , pragma [ only_bind_into ] ( config ) ) and
12761295 PrevStage:: returnMayFlowThrough ( ret , pos , pragma [ only_bind_into ] ( config ) ) and
1277- matchesCall ( ccc , call )
1296+ matchesCall ( ccc , call ) and
1297+ c = ret .getEnclosingCallable ( )
12781298 )
12791299 }
12801300
@@ -1284,12 +1304,12 @@ private module MkStage<StageSig PrevStage> {
12841304 *
12851305 * The call context `cc` records whether the node is reached through an
12861306 * argument in a call, and if so, `summaryCtx` and `argAp` record the
1287- * corresponding parameter and access path of that argument, respectively.
1307+ * corresponding parameter position and access path of that argument, respectively.
12881308 */
12891309 pragma [ nomagic]
12901310 additional predicate fwdFlow (
1291- NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , ApOption argAp , Ap ap ,
1292- Configuration config
1311+ NodeEx node , FlowState state , Cc cc , ParameterPositionOption summaryCtx , ApOption argAp ,
1312+ Ap ap , Configuration config
12931313 ) {
12941314 fwdFlow0 ( node , state , cc , summaryCtx , argAp , ap , config ) and
12951315 PrevStage:: revFlow ( node , state , unbindApa ( getApprox ( ap ) ) , config ) and
@@ -1298,13 +1318,13 @@ private module MkStage<StageSig PrevStage> {
12981318
12991319 pragma [ nomagic]
13001320 private predicate fwdFlow0 (
1301- NodeEx node , FlowState state , Cc cc , ParamNodeOption summaryCtx , ApOption argAp , Ap ap ,
1302- Configuration config
1321+ NodeEx node , FlowState state , Cc cc , ParameterPositionOption summaryCtx , ApOption argAp ,
1322+ Ap ap , Configuration config
13031323 ) {
13041324 sourceNode ( node , state , config ) and
13051325 ( if hasSourceCallCtx ( config ) then cc = ccSomeCall ( ) else cc = ccNone ( ) ) and
13061326 argAp = apNone ( ) and
1307- summaryCtx = TParamNodeNone ( ) and
1327+ summaryCtx = TParameterPositionNone ( ) and
13081328 ap = getApNil ( node )
13091329 or
13101330 exists ( NodeEx mid , FlowState state0 , Ap ap0 , LocalCc localCc |
@@ -1322,15 +1342,15 @@ private module MkStage<StageSig PrevStage> {
13221342 fwdFlow ( mid , pragma [ only_bind_into ] ( state ) , _, _, _, ap , pragma [ only_bind_into ] ( config ) ) and
13231343 jumpStep ( mid , node , config ) and
13241344 cc = ccNone ( ) and
1325- summaryCtx = TParamNodeNone ( ) and
1345+ summaryCtx = TParameterPositionNone ( ) and
13261346 argAp = apNone ( )
13271347 )
13281348 or
13291349 exists ( NodeEx mid , ApNil nil |
13301350 fwdFlow ( mid , state , _, _, _, nil , pragma [ only_bind_into ] ( config ) ) and
13311351 additionalJumpStep ( mid , node , config ) and
13321352 cc = ccNone ( ) and
1333- summaryCtx = TParamNodeNone ( ) and
1353+ summaryCtx = TParameterPositionNone ( ) and
13341354 argAp = apNone ( ) and
13351355 ap = getApNil ( node )
13361356 )
@@ -1339,7 +1359,7 @@ private module MkStage<StageSig PrevStage> {
13391359 fwdFlow ( mid , state0 , _, _, _, nil , pragma [ only_bind_into ] ( config ) ) and
13401360 additionalJumpStateStep ( mid , state0 , node , state , config ) and
13411361 cc = ccNone ( ) and
1342- summaryCtx = TParamNodeNone ( ) and
1362+ summaryCtx = TParameterPositionNone ( ) and
13431363 argAp = apNone ( ) and
13441364 ap = getApNil ( node )
13451365 )
@@ -1362,17 +1382,18 @@ private module MkStage<StageSig PrevStage> {
13621382 apa = getApprox ( ap ) and
13631383 if PrevStage:: parameterMayFlowThrough ( node , apa , config )
13641384 then (
1365- summaryCtx = TParamNodeSome ( node .asNode ( ) ) and argAp = apSome ( ap )
1385+ summaryCtx = TParameterPositionSome ( node .( ParamNodeEx ) .getPosition ( ) ) and
1386+ argAp = apSome ( ap )
13661387 ) else (
1367- summaryCtx = TParamNodeNone ( ) and argAp = apNone ( )
1388+ summaryCtx = TParameterPositionNone ( ) and argAp = apNone ( )
13681389 )
13691390 )
13701391 or
13711392 // flow out of a callable
13721393 fwdFlowOutNotFromArg ( node , state , cc , summaryCtx , argAp , ap , config )
13731394 or
13741395 // flow through a callable
1375- exists ( DataFlowCall call , ParamNode summaryCtx0 , Ap argAp0 |
1396+ exists ( DataFlowCall call , ParameterPosition summaryCtx0 , Ap argAp0 |
13761397 fwdFlowOutFromArg ( call , node , state , summaryCtx0 , argAp0 , ap , config ) and
13771398 fwdFlowIsEntered ( call , cc , summaryCtx , argAp , summaryCtx0 , argAp0 , config )
13781399 )
@@ -1381,7 +1402,7 @@ private module MkStage<StageSig PrevStage> {
13811402 pragma [ nomagic]
13821403 private predicate fwdFlowStore (
13831404 NodeEx node1 , Ap ap1 , TypedContent tc , NodeEx node2 , FlowState state , Cc cc ,
1384- ParamNodeOption summaryCtx , ApOption argAp , Configuration config
1405+ ParameterPositionOption summaryCtx , ApOption argAp , Configuration config
13851406 ) {
13861407 exists ( DataFlowType contentType |
13871408 fwdFlow ( node1 , state , cc , summaryCtx , argAp , ap1 , config ) and
@@ -1406,7 +1427,7 @@ private module MkStage<StageSig PrevStage> {
14061427 pragma [ nomagic]
14071428 private predicate fwdFlowRead (
14081429 Ap ap , Content c , NodeEx node1 , NodeEx node2 , FlowState state , Cc cc ,
1409- ParamNodeOption summaryCtx , ApOption argAp , Configuration config
1430+ ParameterPositionOption summaryCtx , ApOption argAp , Configuration config
14101431 ) {
14111432 fwdFlow ( node1 , state , cc , summaryCtx , argAp , ap , config ) and
14121433 PrevStage:: readStepCand ( node1 , c , node2 , config ) and
@@ -1416,7 +1437,7 @@ private module MkStage<StageSig PrevStage> {
14161437 pragma [ nomagic]
14171438 private predicate fwdFlowIn (
14181439 DataFlowCall call , ParamNodeEx p , FlowState state , Cc outercc , Cc innercc ,
1419- ParamNodeOption summaryCtx , ApOption argAp , Ap ap , Configuration config
1440+ ParameterPositionOption summaryCtx , ApOption argAp , Ap ap , Configuration config
14201441 ) {
14211442 exists ( ArgNodeEx arg , boolean allowsFieldFlow |
14221443 fwdFlow ( arg , state , outercc , summaryCtx , argAp , ap , config ) and
@@ -1428,8 +1449,8 @@ private module MkStage<StageSig PrevStage> {
14281449
14291450 pragma [ nomagic]
14301451 private predicate fwdFlowOutNotFromArg (
1431- NodeEx out , FlowState state , Cc ccOut , ParamNodeOption summaryCtx , ApOption argAp , Ap ap ,
1432- Configuration config
1452+ NodeEx out , FlowState state , Cc ccOut , ParameterPositionOption summaryCtx , ApOption argAp ,
1453+ Ap ap , Configuration config
14331454 ) {
14341455 exists (
14351456 DataFlowCall call , RetNodeEx ret , boolean allowsFieldFlow , CcNoCall innercc ,
@@ -1445,14 +1466,18 @@ private module MkStage<StageSig PrevStage> {
14451466
14461467 pragma [ nomagic]
14471468 private predicate fwdFlowOutFromArg (
1448- DataFlowCall call , NodeEx out , FlowState state , ParamNode summaryCtx , Ap argAp , Ap ap ,
1469+ DataFlowCall call , NodeEx out , FlowState state , ParameterPosition summaryCtx , Ap argAp , Ap ap ,
14491470 Configuration config
14501471 ) {
1451- exists ( RetNodeEx ret , ReturnKindExt kind , boolean allowsFieldFlow , CcCall ccc |
1452- fwdFlow ( ret , state , ccc , TParamNodeSome ( summaryCtx ) , apSome ( argAp ) , ap , config ) and
1453- flowThroughOutOfCall ( call , ccc , ret , kind , out , allowsFieldFlow , config ) and
1472+ exists (
1473+ DataFlowCallable c , RetNodeEx ret , ReturnKindExt kind , boolean allowsFieldFlow , CcCall ccc
1474+ |
1475+ fwdFlow ( pragma [ only_bind_into ] ( ret ) , state , pragma [ only_bind_into ] ( ccc ) ,
1476+ TParameterPositionSome ( pragma [ only_bind_into ] ( summaryCtx ) ) , apSome ( argAp ) , ap , config ) and
1477+ flowThroughOutOfCall ( call , pragma [ only_bind_into ] ( c ) , ccc , ret , kind , out , allowsFieldFlow ,
1478+ config ) and
14541479 ( if allowsFieldFlow = false then ap instanceof ApNil else any ( ) ) and
1455- parameterFlowThroughAllowed ( summaryCtx , kind )
1480+ parameterFlowThroughAllowed ( c , pragma [ only_bind_into ] ( summaryCtx ) , kind )
14561481 )
14571482 }
14581483
@@ -1462,13 +1487,13 @@ private module MkStage<StageSig PrevStage> {
14621487 */
14631488 pragma [ nomagic]
14641489 private predicate fwdFlowIsEntered (
1465- DataFlowCall call , Cc cc , ParamNodeOption summaryCtx , ApOption argAp , ParamNode p , Ap ap ,
1466- Configuration config
1490+ DataFlowCall call , Cc cc , ParameterPositionOption summaryCtx , ApOption argAp ,
1491+ ParameterPosition pos , Ap ap , Configuration config
14671492 ) {
14681493 exists ( ParamNodeEx param |
14691494 fwdFlowIn ( call , param , _, cc , _, summaryCtx , argAp , ap , config ) and
14701495 PrevStage:: parameterMayFlowThrough ( param , unbindApa ( getApprox ( ap ) ) , config ) and
1471- p = param .asNode ( )
1496+ pos = param .getPosition ( )
14721497 )
14731498 }
14741499
@@ -1488,14 +1513,30 @@ private module MkStage<StageSig PrevStage> {
14881513 fwdFlowConsCand ( ap1 , c , ap2 , config )
14891514 }
14901515
1516+ pragma [ nomagic]
1517+ private predicate returnFlowsThrough0 (
1518+ RetNodeEx ret , FlowState state , CcCall ccc , DataFlowCallable c , ParameterPosition ppos ,
1519+ Ap argAp , Ap ap , Configuration config
1520+ ) {
1521+ exists ( boolean allowsFieldFlow |
1522+ fwdFlow ( ret , state , ccc , TParameterPositionSome ( ppos ) , apSome ( argAp ) , ap , config ) and
1523+ flowThroughOutOfCall ( _, c , _, pragma [ only_bind_into ] ( ret ) , _, _, allowsFieldFlow ,
1524+ pragma [ only_bind_into ] ( config ) ) and
1525+ if allowsFieldFlow = false then ap instanceof ApNil else any ( )
1526+ )
1527+ }
1528+
14911529 pragma [ nomagic]
14921530 private predicate returnFlowsThrough (
1493- RetNodeEx ret , ReturnPosition pos , FlowState state , CcCall ccc , ParamNode p , Ap argAp , Ap ap ,
1494- Configuration config
1531+ RetNodeEx ret , ReturnPosition pos , FlowState state , CcCall ccc , ParamNodeEx p , Ap argAp ,
1532+ Ap ap , Configuration config
14951533 ) {
1496- fwdFlow ( ret , state , ccc , TParamNodeSome ( p ) , apSome ( argAp ) , ap , config ) and
1497- pos = ret .getReturnPosition ( ) and
1498- parameterFlowThroughAllowed ( p , pos .getKind ( ) )
1534+ exists ( DataFlowCallable c , ParameterPosition ppos |
1535+ returnFlowsThrough0 ( ret , state , ccc , c , ppos , argAp , ap , config ) and
1536+ p .isParameterOf ( c , ppos ) and
1537+ pos = ret .getReturnPosition ( ) and
1538+ parameterFlowThroughAllowed ( p , pos .getKind ( ) )
1539+ )
14991540 }
15001541
15011542 pragma [ nomagic]
@@ -1506,7 +1547,7 @@ private module MkStage<StageSig PrevStage> {
15061547 flowIntoCall ( call , pragma [ only_bind_into ] ( arg ) , pragma [ only_bind_into ] ( p ) , allowsFieldFlow ,
15071548 pragma [ only_bind_into ] ( config ) ) and
15081549 fwdFlow ( arg , _, _, _, _, pragma [ only_bind_into ] ( argAp ) , pragma [ only_bind_into ] ( config ) ) and
1509- returnFlowsThrough ( _, _, _, _, p . asNode ( ) , pragma [ only_bind_into ] ( argAp ) , _,
1550+ returnFlowsThrough ( _, _, _, _, p , pragma [ only_bind_into ] ( argAp ) , _,
15101551 pragma [ only_bind_into ] ( config ) )
15111552 )
15121553 }
@@ -1671,7 +1712,7 @@ private module MkStage<StageSig PrevStage> {
16711712 revFlow ( p , state , TReturnCtxMaybeFlowThrough ( returnPos ) , apSome ( returnAp ) , ap , config ) and
16721713 flowThroughIntoCall ( call , arg , p , allowsFieldFlow , config ) and
16731714 ( if allowsFieldFlow = false then ap instanceof ApNil else any ( ) ) and
1674- parameterFlowThroughAllowed ( p . asNode ( ) , returnPos .getKind ( ) )
1715+ parameterFlowThroughAllowed ( p , returnPos .getKind ( ) )
16751716 )
16761717 }
16771718
@@ -1763,21 +1804,21 @@ private module MkStage<StageSig PrevStage> {
17631804 ParamNodeEx p , Ap ap , ReturnPosition returnPos , Configuration config
17641805 ) {
17651806 revFlow ( p , _, TReturnCtxMaybeFlowThrough ( returnPos ) , apSome ( _) , ap , config ) and
1766- parameterFlowThroughAllowed ( p . asNode ( ) , returnPos .getKind ( ) )
1807+ parameterFlowThroughAllowed ( p , returnPos .getKind ( ) )
17671808 }
17681809
17691810 pragma [ nomagic]
17701811 predicate parameterMayFlowThrough ( ParamNodeEx p , Ap ap , Configuration config ) {
17711812 exists ( RetNodeEx ret , ReturnPosition pos |
1772- returnFlowsThrough ( ret , pos , _, _, p . asNode ( ) , ap , _, config ) and
1813+ returnFlowsThrough ( ret , pos , _, _, p , ap , _, config ) and
17731814 parameterFlowsThroughRev ( p , ap , pos , config )
17741815 )
17751816 }
17761817
17771818 pragma [ nomagic]
17781819 predicate returnMayFlowThrough ( RetNodeEx ret , ReturnPosition pos , Configuration config ) {
17791820 exists ( ParamNodeEx p , Ap ap |
1780- returnFlowsThrough ( ret , pos , _, _, p . asNode ( ) , ap , _, config ) and
1821+ returnFlowsThrough ( ret , pos , _, _, p , ap , _, config ) and
17811822 parameterFlowsThroughRev ( p , ap , pos , config )
17821823 )
17831824 }
@@ -1803,9 +1844,8 @@ private module MkStage<StageSig PrevStage> {
18031844 conscand = count ( TypedContent f0 , Ap ap | fwdConsCand ( f0 , ap , config ) ) and
18041845 states = count ( FlowState state | fwdFlow ( _, state , _, _, _, _, config ) ) and
18051846 tuples =
1806- count ( NodeEx n , FlowState state , Cc cc , ParamNodeOption summaryCtx , ApOption argAp , Ap ap |
1807- fwdFlow ( n , state , cc , summaryCtx , argAp , ap , config )
1808- )
1847+ count ( NodeEx n , FlowState state , Cc cc , ParameterPositionOption summaryCtx , ApOption argAp ,
1848+ Ap ap | fwdFlow ( n , state , cc , summaryCtx , argAp , ap , config ) )
18091849 or
18101850 fwd = false and
18111851 nodes = count ( NodeEx node | revFlow ( node , _, _, _, _, config ) ) and
@@ -2555,12 +2595,13 @@ private Configuration unbindConf(Configuration conf) {
25552595
25562596pragma [ nomagic]
25572597private predicate nodeMayUseSummary0 (
2558- NodeEx n , ParamNodeEx p , FlowState state , AccessPathApprox apa , Configuration config
2598+ NodeEx n , DataFlowCallable c , ParameterPosition pos , FlowState state , AccessPathApprox apa ,
2599+ Configuration config
25592600) {
25602601 exists ( AccessPathApprox apa0 |
2561- Stage4 :: parameterMayFlowThrough ( p , _ , _ ) and
2602+ c = n . getEnclosingCallable ( ) and
25622603 Stage4:: revFlow ( n , state , TReturnCtxMaybeFlowThrough ( _) , _, apa0 , config ) and
2563- Stage4:: fwdFlow ( n , state , any ( CallContextCall ccc ) , TParamNodeSome ( p . asNode ( ) ) ,
2604+ Stage4:: fwdFlow ( n , state , any ( CallContextCall ccc ) , TParameterPositionSome ( pos ) ,
25642605 TAccessPathApproxSome ( apa ) , apa0 , config )
25652606 )
25662607}
@@ -2569,9 +2610,10 @@ pragma[nomagic]
25692610private predicate nodeMayUseSummary (
25702611 NodeEx n , FlowState state , AccessPathApprox apa , Configuration config
25712612) {
2572- exists ( ParamNodeEx p |
2613+ exists ( DataFlowCallable c , ParameterPosition pos , ParamNodeEx p |
25732614 Stage4:: parameterMayFlowThrough ( p , apa , config ) and
2574- nodeMayUseSummary0 ( n , p , state , apa , config )
2615+ nodeMayUseSummary0 ( n , c , pos , state , apa , config ) and
2616+ p .isParameterOf ( c , pos )
25752617 )
25762618}
25772619
@@ -3504,7 +3546,7 @@ private predicate paramFlowsThrough(
35043546 pathNode ( mid , ret , state , cc , sc , ap , config , _) and
35053547 kind = ret .getKind ( ) and
35063548 apa = ap .getApprox ( ) and
3507- parameterFlowThroughAllowed ( sc .getParamNode ( ) . asNode ( ) , kind )
3549+ parameterFlowThroughAllowed ( sc .getParamNode ( ) , kind )
35083550 )
35093551}
35103552
0 commit comments