@@ -110,12 +110,12 @@ abstract class Configuration extends string {
110
110
/**
111
111
* Holds if data may flow from some source to `sink` for this configuration.
112
112
*/
113
- predicate hasFlowTo ( Node sink ) { hasFlow ( _, sink ) }
113
+ predicate hasFlowTo ( Node sink ) { this . hasFlow ( _, sink ) }
114
114
115
115
/**
116
116
* Holds if data may flow from some source to `sink` for this configuration.
117
117
*/
118
- predicate hasFlowToExpr ( DataFlowExpr sink ) { hasFlowTo ( exprNode ( sink ) ) }
118
+ predicate hasFlowToExpr ( DataFlowExpr sink ) { this . hasFlowTo ( exprNode ( sink ) ) }
119
119
120
120
/**
121
121
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
@@ -244,6 +244,8 @@ private class ParamNodeEx extends NodeEx {
244
244
}
245
245
246
246
int getPosition ( ) { this .isParameterOf ( _, result ) }
247
+
248
+ predicate allowParameterReturnInSelf ( ) { allowParameterReturnInSelfCached ( this .asNode ( ) ) }
247
249
}
248
250
249
251
private class RetNodeEx extends NodeEx {
@@ -744,8 +746,12 @@ private module Stage1 {
744
746
returnFlowCallableNodeCand ( c , kind , config ) and
745
747
p .getEnclosingCallable ( ) = c and
746
748
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
+ )
749
755
)
750
756
}
751
757
@@ -1394,8 +1400,12 @@ private module Stage2 {
1394
1400
fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
1395
1401
kind = ret .getKind ( ) and
1396
1402
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
+ )
1399
1409
)
1400
1410
}
1401
1411
@@ -2083,8 +2093,12 @@ private module Stage3 {
2083
2093
fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
2084
2094
kind = ret .getKind ( ) and
2085
2095
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
+ )
2088
2102
)
2089
2103
}
2090
2104
@@ -2843,8 +2857,12 @@ private module Stage4 {
2843
2857
fwdFlow ( ret , any ( CcCall ccc ) , apSome ( ap ) , ap0 , config ) and
2844
2858
kind = ret .getKind ( ) and
2845
2859
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
+ )
2848
2866
)
2849
2867
}
2850
2868
@@ -2917,6 +2935,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
2917
2935
2918
2936
int getParameterPos ( ) { p .isParameterOf ( _, result ) }
2919
2937
2938
+ ParamNodeEx getParamNode ( ) { result = p }
2939
+
2920
2940
override string toString ( ) { result = p + ": " + ap }
2921
2941
2922
2942
predicate hasLocationInfo (
@@ -3170,7 +3190,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
3170
3190
}
3171
3191
3172
3192
override string toString ( ) {
3173
- result = "[" + this .toStringImpl ( true ) + length ( ) .toString ( ) + ")]"
3193
+ result = "[" + this .toStringImpl ( true ) + this . length ( ) .toString ( ) + ")]"
3174
3194
or
3175
3195
result = "[" + this .toStringImpl ( false )
3176
3196
}
@@ -3309,9 +3329,11 @@ abstract private class PathNodeImpl extends PathNode {
3309
3329
result = " <" + this .( PathNodeMid ) .getCallContext ( ) .toString ( ) + ">"
3310
3330
}
3311
3331
3312
- override string toString ( ) { result = this .getNodeEx ( ) .toString ( ) + ppAp ( ) }
3332
+ override string toString ( ) { result = this .getNodeEx ( ) .toString ( ) + this . ppAp ( ) }
3313
3333
3314
- override string toStringWithContext ( ) { result = this .getNodeEx ( ) .toString ( ) + ppAp ( ) + ppCtx ( ) }
3334
+ override string toStringWithContext ( ) {
3335
+ result = this .getNodeEx ( ) .toString ( ) + this .ppAp ( ) + this .ppCtx ( )
3336
+ }
3315
3337
3316
3338
override predicate hasLocationInfo (
3317
3339
string filepath , int startline , int startcolumn , int endline , int endcolumn
@@ -3379,11 +3401,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
3379
3401
3380
3402
override PathNodeImpl getASuccessorImpl ( ) {
3381
3403
// an intermediate step to another intermediate node
3382
- result = getSuccMid ( )
3404
+ result = this . getSuccMid ( )
3383
3405
or
3384
3406
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
3385
3407
exists ( PathNodeMid mid , PathNodeSink sink |
3386
- mid = getSuccMid ( ) and
3408
+ mid = this . getSuccMid ( ) and
3387
3409
mid .getNodeEx ( ) = sink .getNodeEx ( ) and
3388
3410
mid .getAp ( ) instanceof AccessPathNil and
3389
3411
sink .getConfiguration ( ) = unbindConf ( mid .getConfiguration ( ) ) and
@@ -3460,7 +3482,7 @@ private predicate pathStep(
3460
3482
exists ( TypedContent tc | pathReadStep ( mid , node , ap .push ( tc ) , tc , cc ) ) and
3461
3483
sc = mid .getSummaryCtx ( )
3462
3484
or
3463
- pathIntoCallable ( mid , node , _, cc , sc , _) and ap = mid .getAp ( )
3485
+ pathIntoCallable ( mid , node , _, cc , sc , _, _ ) and ap = mid .getAp ( )
3464
3486
or
3465
3487
pathOutOfCallable ( mid , node , cc ) and ap = mid .getAp ( ) and sc instanceof SummaryCtxNone
3466
3488
or
@@ -3537,14 +3559,16 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
3537
3559
*/
3538
3560
pragma [ noinline]
3539
3561
private 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
3541
3564
) {
3542
3565
exists ( ArgNode arg |
3543
3566
arg = mid .getNodeEx ( ) .asNode ( ) and
3544
3567
cc = mid .getCallContext ( ) and
3545
3568
arg .argumentOf ( call , i ) and
3546
3569
ap = mid .getAp ( ) and
3547
- apa = ap .getApprox ( )
3570
+ apa = ap .getApprox ( ) and
3571
+ config = mid .getConfiguration ( )
3548
3572
)
3549
3573
}
3550
3574
@@ -3561,12 +3585,14 @@ private predicate parameterCand(
3561
3585
pragma [ nomagic]
3562
3586
private predicate pathIntoCallable0 (
3563
3587
PathNodeMid mid , DataFlowCallable callable , int i , CallContext outercc , DataFlowCall call ,
3564
- AccessPath ap
3588
+ AccessPath ap , Configuration config
3565
3589
) {
3566
3590
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
3568
3593
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 ) )
3570
3596
)
3571
3597
}
3572
3598
@@ -3575,12 +3601,13 @@ private predicate pathIntoCallable0(
3575
3601
* before and after entering the callable are `outercc` and `innercc`,
3576
3602
* respectively.
3577
3603
*/
3604
+ pragma [ nomagic]
3578
3605
private predicate pathIntoCallable (
3579
3606
PathNodeMid mid , ParamNodeEx p , CallContext outercc , CallContextCall innercc , SummaryCtx sc ,
3580
- DataFlowCall call
3607
+ DataFlowCall call , Configuration config
3581
3608
) {
3582
3609
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
3584
3611
p .isParameterOf ( callable , i ) and
3585
3612
(
3586
3613
sc = TSummaryCtxSome ( p , ap )
@@ -3610,18 +3637,23 @@ private predicate paramFlowsThrough(
3610
3637
ap = mid .getAp ( ) and
3611
3638
apa = ap .getApprox ( ) and
3612
3639
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
+ )
3614
3646
)
3615
3647
}
3616
3648
3617
3649
pragma [ nomagic]
3618
3650
private predicate pathThroughCallable0 (
3619
3651
DataFlowCall call , PathNodeMid mid , ReturnKindExt kind , CallContext cc , AccessPath ap ,
3620
- AccessPathApprox apa
3652
+ AccessPathApprox apa , Configuration config
3621
3653
) {
3622
3654
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 )
3625
3657
)
3626
3658
}
3627
3659
@@ -3631,9 +3663,9 @@ private predicate pathThroughCallable0(
3631
3663
*/
3632
3664
pragma [ noinline]
3633
3665
private 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 )
3637
3669
)
3638
3670
}
3639
3671
@@ -3647,10 +3679,11 @@ private module Subpaths {
3647
3679
PathNode arg , ParamNodeEx par , SummaryCtxSome sc , CallContext innercc , ReturnKindExt kind ,
3648
3680
NodeEx out , AccessPath apout
3649
3681
) {
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
+ )
3654
3687
}
3655
3688
3656
3689
/**
0 commit comments