@@ -2572,23 +2572,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
2572
2572
2573
2573
pragma [ nomagic]
2574
2574
private predicate revFlowThroughArg (
2575
- DataFlowCall call , ArgNodeEx arg , FlowState state , ReturnCtx returnCtx , ApOption returnAp ,
2576
- Ap ap
2575
+ DataFlowCall call , ArgNodeEx arg , ParamNodeEx p , FlowState state , ReturnCtx returnCtx ,
2576
+ ApOption returnAp , Ap ap
2577
2577
) {
2578
- exists ( ParamNodeEx p , Ap innerReturnAp |
2578
+ exists ( Ap innerReturnAp |
2579
2579
revFlowThrough ( call , returnCtx , p , state , _, returnAp , ap , innerReturnAp ) and
2580
2580
flowThroughIntoCall ( call , arg , p , _, ap , innerReturnAp )
2581
2581
)
2582
2582
}
2583
2583
2584
2584
pragma [ nomagic]
2585
- predicate callMayFlowThroughRev ( DataFlowCall call ) {
2585
+ additional predicate callMayFlowThroughRev ( DataFlowCall call , ParamNodeEx p ) {
2586
2586
exists ( ArgNodeEx arg , FlowState state , ReturnCtx returnCtx , ApOption returnAp , Ap ap |
2587
2587
revFlow ( arg , state , returnCtx , returnAp , ap ) and
2588
- revFlowThroughArg ( call , arg , state , returnCtx , returnAp , ap )
2588
+ revFlowThroughArg ( call , arg , p , state , returnCtx , returnAp , ap )
2589
2589
)
2590
2590
}
2591
2591
2592
+ predicate callMayFlowThroughRev ( DataFlowCall call ) { callMayFlowThroughRev ( call , _) }
2593
+
2592
2594
predicate callEdgeArgParam (
2593
2595
DataFlowCall call , DataFlowCallable c , ArgNodeEx arg , ParamNodeEx p ,
2594
2596
boolean allowsFieldFlow , Ap ap
@@ -3856,24 +3858,68 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
3856
3858
private module StoreReadMatchingInput implements StoreReadMatchingInputSig {
3857
3859
class NodeEx = NodeExAlias ;
3858
3860
3859
- predicate nodeRange ( NodeEx node , boolean fromArg ) {
3860
- exists ( PrevStage:: Ap ap |
3861
- PrevStage:: revFlowAp ( node , ap ) and
3861
+ /**
3862
+ * Gets a call context for `node` that is relevant for either improved virtual
3863
+ * dispatch or for flow-through.
3864
+ */
3865
+ pragma [ nomagic]
3866
+ private DataFlowCallOption getACallCtx ( NodeEx node , PrevStage:: Ap ap , boolean fromArg ) {
3867
+ exists ( PrevStage:: Cc cc , ParamNodeOption summaryCtx , PrevStage:: ApOption argAp |
3868
+ PrevStage:: fwdFlow ( node , _, cc , summaryCtx , _, argAp , _, ap , _)
3869
+ |
3870
+ PrevStage:: instanceofCcCall ( cc ) and
3871
+ fromArg = true and
3862
3872
(
3863
- ap = true
3864
- or
3865
- PrevStage:: storeStepCand ( node , ap , _, _, _, _)
3873
+ // virtual dispatch may be improved
3874
+ exists ( DataFlowCall call , DataFlowCallable c |
3875
+ PrevStage:: callEdgeArgParam ( call , c , _, _, _, _) and
3876
+ cc = Stage2Param:: getSpecificCallContextCall ( call , c ) and
3877
+ c = node .getEnclosingCallable ( ) and
3878
+ result = TDataFlowCallSome ( call )
3879
+ )
3866
3880
or
3867
- PrevStage:: readStepCand ( _, _, node )
3881
+ not cc = Stage2Param:: getSpecificCallContextCall ( _, _) and
3882
+ (
3883
+ // flow-through not possible
3884
+ summaryCtx instanceof TParamNodeNone and
3885
+ result = TDataFlowCallNone ( )
3886
+ or
3887
+ exists ( DataFlowCall call , ParamNodeEx p , PrevStage:: Ap argApSome |
3888
+ summaryCtx = TParamNodeSome ( p .asNode ( ) ) and
3889
+ argAp = PrevStage:: apSome ( argApSome )
3890
+ |
3891
+ if
3892
+ PrevStage:: parameterMayFlowThrough ( p , argApSome ) and
3893
+ PrevStage:: callMayFlowThroughRev ( call , p )
3894
+ then
3895
+ // flow-through possible
3896
+ result = TDataFlowCallSome ( call )
3897
+ else (
3898
+ // flow-through not possible, but `node` can reach a sink without
3899
+ // flowing back out
3900
+ PrevStage:: callEdgeArgParam ( call , _, _, p , _, _) and
3901
+ result = TDataFlowCallNone ( )
3902
+ )
3903
+ )
3904
+ )
3868
3905
)
3906
+ or
3907
+ PrevStage:: instanceofCcNoCall ( cc ) and
3908
+ fromArg = false and
3909
+ result = TDataFlowCallNone ( )
3910
+ )
3911
+ }
3912
+
3913
+ predicate nodeRange ( NodeEx node , boolean fromArg , DataFlowCallOption summaryCtx ) {
3914
+ exists ( PrevStage:: Ap ap |
3915
+ PrevStage:: revFlowAp ( node , ap ) and
3916
+ summaryCtx = getACallCtx ( node , ap , fromArg )
3869
3917
|
3870
- exists ( PrevStage:: Cc cc | PrevStage:: fwdFlow ( node , _, cc , _, _, _, _, ap , _) |
3871
- PrevStage:: instanceofCcCall ( cc ) and
3872
- fromArg = true
3873
- or
3874
- PrevStage:: instanceofCcNoCall ( cc ) and
3875
- fromArg = false
3876
- )
3918
+ ap = true
3919
+ or
3920
+ PrevStage:: storeStepCand ( node , ap , _, _, _, _)
3921
+ or
3922
+ PrevStage:: readStepCand ( _, _, node )
3877
3923
)
3878
3924
}
3879
3925
@@ -3899,12 +3945,51 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
3899
3945
)
3900
3946
}
3901
3947
3902
- predicate callEdgeArgParam ( NodeEx arg , NodeEx param ) {
3903
- PrevStage:: callEdgeArgParam ( _, _, arg , param , true , true )
3948
+ pragma [ nomagic]
3949
+ private predicate callEdgeArgParam (
3950
+ DataFlowCall call , DataFlowCallable c , NodeEx arg , NodeEx param ,
3951
+ DataFlowCallOption innerCallCtx
3952
+ ) {
3953
+ PrevStage:: callEdgeArgParam ( call , c , arg , param , true , true ) and
3954
+ innerCallCtx = getACallCtx ( param , true , true ) and
3955
+ (
3956
+ innerCallCtx = TDataFlowCallNone ( )
3957
+ or
3958
+ innerCallCtx = TDataFlowCallSome ( call )
3959
+ )
3960
+ }
3961
+
3962
+ pragma [ nomagic]
3963
+ private predicate callEdgeArgParamCallContextReduced (
3964
+ DataFlowCall call , NodeEx arg , NodeEx param , Stage2Param:: CcCall outerCcCall ,
3965
+ DataFlowCallOption innerCallCtx
3966
+ ) {
3967
+ exists ( DataFlowCallable c |
3968
+ callEdgeArgParam ( call , c , arg , param , innerCallCtx ) and
3969
+ Stage2Param:: viableImplCallContextReduced ( call , outerCcCall ) = c
3970
+ )
3971
+ }
3972
+
3973
+ bindingset [ outerCallCtx]
3974
+ predicate callEdgeArgParam (
3975
+ NodeEx arg , NodeEx param , DataFlowCallOption outerCallCtx , DataFlowCallOption innerCallCtx
3976
+ ) {
3977
+ exists ( DataFlowCall call | callEdgeArgParam ( call , _, arg , param , innerCallCtx ) |
3978
+ outerCallCtx = TDataFlowCallNone ( )
3979
+ or
3980
+ exists ( DataFlowCall outerCall , Stage2Param:: CcCall outerCcCall |
3981
+ outerCallCtx = TDataFlowCallSome ( outerCall ) and
3982
+ outerCcCall = Stage2Param:: getCallContextCall ( outerCall , call .getEnclosingCallable ( ) )
3983
+ |
3984
+ callEdgeArgParamCallContextReduced ( call , arg , param , outerCcCall , innerCallCtx )
3985
+ or
3986
+ Stage2Param:: viableImplNotCallContextReduced ( call , outerCcCall )
3987
+ )
3988
+ )
3904
3989
}
3905
3990
3906
- predicate callEdgeReturn ( NodeEx ret , NodeEx out , boolean mayFlowThrough ) {
3907
- PrevStage:: callEdgeReturn ( _ , _, ret , _, out , true , true ) and
3991
+ predicate callEdgeReturn ( DataFlowCall call , NodeEx ret , NodeEx out , boolean mayFlowThrough ) {
3992
+ PrevStage:: callEdgeReturn ( call , _, ret , _, out , true , true ) and
3908
3993
if flowThroughOutOfCall ( ret , out ) then mayFlowThrough = true else mayFlowThrough = false
3909
3994
}
3910
3995
0 commit comments