@@ -110,12 +110,12 @@ abstract class Configuration extends string {
110110 /**
111111 * Holds if data may flow from some source to `sink` for this configuration.
112112 */
113- predicate hasFlowTo ( Node sink ) { hasFlow ( _, sink ) }
113+ predicate hasFlowTo ( Node sink ) { this . hasFlow ( _, sink ) }
114114
115115 /**
116116 * Holds if data may flow from some source to `sink` for this configuration.
117117 */
118- predicate hasFlowToExpr ( DataFlowExpr sink ) { hasFlowTo ( exprNode ( sink ) ) }
118+ predicate hasFlowToExpr ( DataFlowExpr sink ) { this . hasFlowTo ( exprNode ( sink ) ) }
119119
120120 /**
121121 * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
244244 }
245245
246246 int getPosition ( ) { this .isParameterOf ( _, result ) }
247+
248+ predicate allowParameterReturnInSelf ( ) { allowParameterReturnInSelfCached ( this .asNode ( ) ) }
247249}
248250
249251private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
744746 returnFlowCallableNodeCand ( c , kind , config ) and
745747 p .getEnclosingCallable ( ) = c and
746748 exists ( ap ) and
747- // we don't expect a parameter to return stored in itself
748- not kind .( ParamUpdateReturnKind ) .getPosition ( ) = p .getPosition ( )
749+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
750+ (
751+ not kind .( ParamUpdateReturnKind ) .getPosition ( ) = p .getPosition ( )
752+ or
753+ p .allowParameterReturnInSelf ( )
754+ )
749755 )
750756 }
751757
@@ -1394,8 +1400,12 @@ private module Stage2 {
13941400 fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
13951401 kind = ret .getKind ( ) and
13961402 p .getPosition ( ) = pos and
1397- // we don't expect a parameter to return stored in itself
1398- not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
1403+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
1404+ (
1405+ not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
1406+ or
1407+ p .allowParameterReturnInSelf ( )
1408+ )
13991409 )
14001410 }
14011411
@@ -2083,8 +2093,12 @@ private module Stage3 {
20832093 fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
20842094 kind = ret .getKind ( ) and
20852095 p .getPosition ( ) = pos and
2086- // we don't expect a parameter to return stored in itself
2087- not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
2096+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
2097+ (
2098+ not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
2099+ or
2100+ p .allowParameterReturnInSelf ( )
2101+ )
20882102 )
20892103 }
20902104
@@ -2843,8 +2857,12 @@ private module Stage4 {
28432857 fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
28442858 kind = ret .getKind ( ) and
28452859 p .getPosition ( ) = pos and
2846- // we don't expect a parameter to return stored in itself
2847- not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
2860+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
2861+ (
2862+ not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
2863+ or
2864+ p .allowParameterReturnInSelf ( )
2865+ )
28482866 )
28492867 }
28502868
@@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
29172935
29182936 int getParameterPos ( ) { p .isParameterOf ( _, result ) }
29192937
2938+ ParamNodeEx getParamNode ( ) { result = p }
2939+
29202940 override string toString ( ) { result = p + ": " + ap }
29212941
29222942 predicate hasLocationInfo (
@@ -3170,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
31703190 }
31713191
31723192 override string toString ( ) {
3173- result = "[" + this .toStringImpl ( true ) + length ( ) .toString ( ) + ")]"
3193+ result = "[" + this .toStringImpl ( true ) + this . length ( ) .toString ( ) + ")]"
31743194 or
31753195 result = "[" + this .toStringImpl ( false )
31763196 }
@@ -3309,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
33093329 result = " <" + this .( PathNodeMid ) .getCallContext ( ) .toString ( ) + ">"
33103330 }
33113331
3312- override string toString ( ) { result = this .getNodeEx ( ) .toString ( ) + ppAp ( ) }
3332+ override string toString ( ) { result = this .getNodeEx ( ) .toString ( ) + this . ppAp ( ) }
33133333
3314- override string toStringWithContext ( ) { result = this .getNodeEx ( ) .toString ( ) + ppAp ( ) + ppCtx ( ) }
3334+ override string toStringWithContext ( ) {
3335+ result = this .getNodeEx ( ) .toString ( ) + this .ppAp ( ) + this .ppCtx ( )
3336+ }
33153337
33163338 override predicate hasLocationInfo (
33173339 string filepath , int startline , int startcolumn , int endline , int endcolumn
@@ -3379,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
33793401
33803402 override PathNodeImpl getASuccessorImpl ( ) {
33813403 // an intermediate step to another intermediate node
3382- result = getSuccMid ( )
3404+ result = this . getSuccMid ( )
33833405 or
33843406 // a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
33853407 exists ( PathNodeMid mid , PathNodeSink sink |
3386- mid = getSuccMid ( ) and
3408+ mid = this . getSuccMid ( ) and
33873409 mid .getNodeEx ( ) = sink .getNodeEx ( ) and
33883410 mid .getAp ( ) instanceof AccessPathNil and
33893411 sink .getConfiguration ( ) = unbindConf ( mid .getConfiguration ( ) ) and
@@ -3460,7 +3482,7 @@ private predicate pathStep(
34603482 exists ( TypedContent tc | pathReadStep ( mid , node , ap .push ( tc ) , tc , cc ) ) and
34613483 sc = mid .getSummaryCtx ( )
34623484 or
3463- pathIntoCallable ( mid , node , _, cc , sc , _) and ap = mid .getAp ( )
3485+ pathIntoCallable ( mid , node , _, cc , sc , _, _ ) and ap = mid .getAp ( )
34643486 or
34653487 pathOutOfCallable ( mid , node , cc ) and ap = mid .getAp ( ) and sc instanceof SummaryCtxNone
34663488 or
@@ -3537,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
35373559 */
35383560pragma [ noinline]
35393561private predicate pathIntoArg (
3540- PathNodeMid mid , int i , CallContext cc , DataFlowCall call , AccessPath ap , AccessPathApprox apa
3562+ PathNodeMid mid , int i , CallContext cc , DataFlowCall call , AccessPath ap , AccessPathApprox apa ,
3563+ Configuration config
35413564) {
35423565 exists ( ArgNode arg |
35433566 arg = mid .getNodeEx ( ) .asNode ( ) and
35443567 cc = mid .getCallContext ( ) and
35453568 arg .argumentOf ( call , i ) and
35463569 ap = mid .getAp ( ) and
3547- apa = ap .getApprox ( )
3570+ apa = ap .getApprox ( ) and
3571+ config = mid .getConfiguration ( )
35483572 )
35493573}
35503574
@@ -3561,12 +3585,14 @@ private predicate parameterCand(
35613585pragma [ nomagic]
35623586private predicate pathIntoCallable0 (
35633587 PathNodeMid mid , DataFlowCallable callable , int i , CallContext outercc , DataFlowCall call ,
3564- AccessPath ap
3588+ AccessPath ap , Configuration config
35653589) {
35663590 exists ( AccessPathApprox apa |
3567- pathIntoArg ( mid , i , outercc , call , ap , apa ) and
3591+ pathIntoArg ( mid , pragma [ only_bind_into ] ( i ) , outercc , call , ap , pragma [ only_bind_into ] ( apa ) ,
3592+ pragma [ only_bind_into ] ( config ) ) and
35683593 callable = resolveCall ( call , outercc ) and
3569- parameterCand ( callable , any ( int j | j <= i and j >= i ) , apa , mid .getConfiguration ( ) )
3594+ parameterCand ( callable , pragma [ only_bind_into ] ( i ) , pragma [ only_bind_into ] ( apa ) ,
3595+ pragma [ only_bind_into ] ( config ) )
35703596 )
35713597}
35723598
@@ -3575,12 +3601,13 @@ private predicate pathIntoCallable0(
35753601 * before and after entering the callable are `outercc` and `innercc`,
35763602 * respectively.
35773603 */
3604+ pragma [ nomagic]
35783605private predicate pathIntoCallable (
35793606 PathNodeMid mid , ParamNodeEx p , CallContext outercc , CallContextCall innercc , SummaryCtx sc ,
3580- DataFlowCall call
3607+ DataFlowCall call , Configuration config
35813608) {
35823609 exists ( int i , DataFlowCallable callable , AccessPath ap |
3583- pathIntoCallable0 ( mid , callable , i , outercc , call , ap ) and
3610+ pathIntoCallable0 ( mid , callable , i , outercc , call , ap , config ) and
35843611 p .isParameterOf ( callable , i ) and
35853612 (
35863613 sc = TSummaryCtxSome ( p , ap )
@@ -3610,18 +3637,23 @@ private predicate paramFlowsThrough(
36103637 ap = mid .getAp ( ) and
36113638 apa = ap .getApprox ( ) and
36123639 pos = sc .getParameterPos ( ) and
3613- not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
3640+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
3641+ (
3642+ not kind .( ParamUpdateReturnKind ) .getPosition ( ) = pos
3643+ or
3644+ sc .getParamNode ( ) .allowParameterReturnInSelf ( )
3645+ )
36143646 )
36153647}
36163648
36173649pragma [ nomagic]
36183650private predicate pathThroughCallable0 (
36193651 DataFlowCall call , PathNodeMid mid , ReturnKindExt kind , CallContext cc , AccessPath ap ,
3620- AccessPathApprox apa
3652+ AccessPathApprox apa , Configuration config
36213653) {
36223654 exists ( CallContext innercc , SummaryCtx sc |
3623- pathIntoCallable ( mid , _, cc , innercc , sc , call ) and
3624- paramFlowsThrough ( kind , innercc , sc , ap , apa , unbindConf ( mid . getConfiguration ( ) ) )
3655+ pathIntoCallable ( mid , _, cc , innercc , sc , call , config ) and
3656+ paramFlowsThrough ( kind , innercc , sc , ap , apa , config )
36253657 )
36263658}
36273659
@@ -3631,9 +3663,9 @@ private predicate pathThroughCallable0(
36313663 */
36323664pragma [ noinline]
36333665private predicate pathThroughCallable ( PathNodeMid mid , NodeEx out , CallContext cc , AccessPath ap ) {
3634- exists ( DataFlowCall call , ReturnKindExt kind , AccessPathApprox apa |
3635- pathThroughCallable0 ( call , mid , kind , cc , ap , apa ) and
3636- out = getAnOutNodeFlow ( kind , call , apa , unbindConf ( mid . getConfiguration ( ) ) )
3666+ exists ( DataFlowCall call , ReturnKindExt kind , AccessPathApprox apa , Configuration config |
3667+ pathThroughCallable0 ( call , mid , kind , cc , ap , apa , config ) and
3668+ out = getAnOutNodeFlow ( kind , call , apa , config )
36373669 )
36383670}
36393671
@@ -3647,10 +3679,11 @@ private module Subpaths {
36473679 PathNode arg , ParamNodeEx par , SummaryCtxSome sc , CallContext innercc , ReturnKindExt kind ,
36483680 NodeEx out , AccessPath apout
36493681 ) {
3650- pathThroughCallable ( arg , out , _, pragma [ only_bind_into ] ( apout ) ) and
3651- pathIntoCallable ( arg , par , _, innercc , sc , _) and
3652- paramFlowsThrough ( kind , innercc , sc , pragma [ only_bind_into ] ( apout ) , _,
3653- unbindConf ( arg .getConfiguration ( ) ) )
3682+ exists ( Configuration config |
3683+ pathThroughCallable ( arg , out , _, pragma [ only_bind_into ] ( apout ) ) and
3684+ pathIntoCallable ( arg , par , _, innercc , sc , _, config ) and
3685+ paramFlowsThrough ( kind , innercc , sc , pragma [ only_bind_into ] ( apout ) , _, unbindConf ( config ) )
3686+ )
36543687 }
36553688
36563689 /**
0 commit comments