@@ -1616,9 +1616,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1616
1616
)
1617
1617
}
1618
1618
1619
- private newtype TSummaryCtx =
1620
- TSummaryCtxNone ( ) or
1621
- TSummaryCtxSome ( ParamNodeEx p , FlowState state , Typ t , Ap ap ) {
1619
+ additional newtype TSummaryCtx =
1620
+ additional TSummaryCtxNone ( ) or
1621
+ additional TSummaryCtxSome ( ParamNodeEx p , FlowState state , Typ t , Ap ap ) {
1622
1622
fwdFlowIn ( p , _, state , _, t , ap , true )
1623
1623
}
1624
1624
@@ -1628,21 +1628,21 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1628
1628
*
1629
1629
* Summaries are only created for parameters that may flow through.
1630
1630
*/
1631
- private class SummaryCtx extends TSummaryCtx {
1631
+ additional class SummaryCtx extends TSummaryCtx {
1632
1632
abstract string toString ( ) ;
1633
1633
1634
1634
abstract Location getLocation ( ) ;
1635
1635
}
1636
1636
1637
1637
/** A summary context from which no flow summary can be generated. */
1638
- private class SummaryCtxNone extends SummaryCtx , TSummaryCtxNone {
1638
+ additional class SummaryCtxNone extends SummaryCtx , TSummaryCtxNone {
1639
1639
override string toString ( ) { result = "<none>" }
1640
1640
1641
1641
override Location getLocation ( ) { result .hasLocationInfo ( "" , 0 , 0 , 0 , 0 ) }
1642
1642
}
1643
1643
1644
1644
/** A summary context from which a flow summary can be generated. */
1645
- private class SummaryCtxSome extends SummaryCtx , TSummaryCtxSome {
1645
+ additional class SummaryCtxSome extends SummaryCtx , TSummaryCtxSome {
1646
1646
private ParamNodeEx p ;
1647
1647
private FlowState state ;
1648
1648
private Typ t ;
@@ -2650,23 +2650,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
2650
2650
2651
2651
pragma [ nomagic]
2652
2652
private predicate revFlowThroughArg (
2653
- DataFlowCall call , ArgNodeEx arg , FlowState state , ReturnCtx returnCtx , ApOption returnAp ,
2654
- Ap ap
2653
+ DataFlowCall call , ArgNodeEx arg , ParamNodeEx p , FlowState state , ReturnCtx returnCtx ,
2654
+ ApOption returnAp , Ap ap
2655
2655
) {
2656
- exists ( ParamNodeEx p , Ap innerReturnAp |
2656
+ exists ( Ap innerReturnAp |
2657
2657
revFlowThrough ( call , returnCtx , p , state , _, returnAp , ap , innerReturnAp ) and
2658
2658
flowThroughIntoCall ( call , arg , p , _, ap , innerReturnAp )
2659
2659
)
2660
2660
}
2661
2661
2662
2662
pragma [ nomagic]
2663
- predicate callMayFlowThroughRev ( DataFlowCall call ) {
2663
+ additional predicate callMayFlowThroughRev ( DataFlowCall call , ParamNodeEx p ) {
2664
2664
exists ( ArgNodeEx arg , FlowState state , ReturnCtx returnCtx , ApOption returnAp , Ap ap |
2665
2665
revFlow ( arg , state , returnCtx , returnAp , ap ) and
2666
- revFlowThroughArg ( call , arg , state , returnCtx , returnAp , ap )
2666
+ revFlowThroughArg ( call , arg , p , state , returnCtx , returnAp , ap )
2667
2667
)
2668
2668
}
2669
2669
2670
+ predicate callMayFlowThroughRev ( DataFlowCall call ) { callMayFlowThroughRev ( call , _) }
2671
+
2670
2672
predicate callEdgeArgParam (
2671
2673
DataFlowCall call , DataFlowCallable c , ArgNodeEx arg , ParamNodeEx p ,
2672
2674
boolean allowsFieldFlow , Ap ap
@@ -3931,24 +3933,67 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
3931
3933
private module StoreReadMatchingInput implements StoreReadMatchingInputSig {
3932
3934
class NodeEx = NodeExAlias ;
3933
3935
3934
- predicate nodeRange ( NodeEx node , boolean fromArg ) {
3935
- exists ( PrevStage:: Ap ap |
3936
- PrevStage:: revFlowAp ( node , ap ) and
3936
+ /**
3937
+ * Gets a call context for `node` that is relevant for either improved virtual
3938
+ * dispatch or for flow-through.
3939
+ */
3940
+ pragma [ nomagic]
3941
+ private DataFlowCallOption getACallCtx ( NodeEx node , PrevStage:: Ap ap , boolean fromArg ) {
3942
+ exists ( PrevStage:: Cc cc , PrevStage:: SummaryCtx summaryCtx |
3943
+ PrevStage:: fwdFlow ( node , _, cc , summaryCtx , _, ap , _)
3944
+ |
3945
+ PrevStage:: instanceofCcCall ( cc ) and
3946
+ fromArg = true and
3937
3947
(
3938
- ap = true
3939
- or
3940
- PrevStage:: storeStepCand ( node , ap , _, _, _, _)
3948
+ // virtual dispatch may be improved
3949
+ exists ( DataFlowCall call , DataFlowCallable c |
3950
+ PrevStage:: callEdgeArgParam ( call , c , _, _, _, _) and
3951
+ cc = Stage2Param:: getSpecificCallContextCall ( call , c ) and
3952
+ c = node .getEnclosingCallable ( ) and
3953
+ result = TDataFlowCallSome ( call )
3954
+ )
3941
3955
or
3942
- PrevStage:: readStepCand ( _, _, node )
3956
+ not cc = Stage2Param:: getSpecificCallContextCall ( _, _) and
3957
+ (
3958
+ // flow-through not possible
3959
+ summaryCtx instanceof PrevStage:: SummaryCtxNone and
3960
+ result = TDataFlowCallNone ( )
3961
+ or
3962
+ exists ( DataFlowCall call , ParamNodeEx p , PrevStage:: Ap argAp |
3963
+ summaryCtx = PrevStage:: TSummaryCtxSome ( p , _, _, argAp )
3964
+ |
3965
+ if
3966
+ PrevStage:: parameterMayFlowThrough ( p , argAp ) and
3967
+ PrevStage:: callMayFlowThroughRev ( call , p )
3968
+ then
3969
+ // flow-through possible
3970
+ result = TDataFlowCallSome ( call )
3971
+ else (
3972
+ // flow-through not possible, but `node` can reach a sink without
3973
+ // flowing back out
3974
+ PrevStage:: callEdgeArgParam ( call , _, _, p , _, _) and
3975
+ result = TDataFlowCallNone ( )
3976
+ )
3977
+ )
3978
+ )
3943
3979
)
3980
+ or
3981
+ PrevStage:: instanceofCcNoCall ( cc ) and
3982
+ fromArg = false and
3983
+ result = TDataFlowCallNone ( )
3984
+ )
3985
+ }
3986
+
3987
+ predicate nodeRange ( NodeEx node , boolean fromArg , DataFlowCallOption summaryCtx ) {
3988
+ exists ( PrevStage:: Ap ap |
3989
+ PrevStage:: revFlowAp ( node , ap ) and
3990
+ summaryCtx = getACallCtx ( node , ap , fromArg )
3944
3991
|
3945
- exists ( PrevStage:: Cc cc | PrevStage:: fwdFlow ( node , _, cc , _, _, ap , _) |
3946
- PrevStage:: instanceofCcCall ( cc ) and
3947
- fromArg = true
3948
- or
3949
- PrevStage:: instanceofCcNoCall ( cc ) and
3950
- fromArg = false
3951
- )
3992
+ ap = true
3993
+ or
3994
+ PrevStage:: storeStepCand ( node , ap , _, _, _, _)
3995
+ or
3996
+ PrevStage:: readStepCand ( _, _, node )
3952
3997
)
3953
3998
}
3954
3999
@@ -3974,12 +4019,51 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
3974
4019
)
3975
4020
}
3976
4021
3977
- predicate callEdgeArgParam ( NodeEx arg , NodeEx param ) {
3978
- PrevStage:: callEdgeArgParam ( _, _, arg , param , true , true )
4022
+ pragma [ nomagic]
4023
+ private predicate callEdgeArgParam (
4024
+ DataFlowCall call , DataFlowCallable c , NodeEx arg , NodeEx param ,
4025
+ DataFlowCallOption innerCallCtx
4026
+ ) {
4027
+ PrevStage:: callEdgeArgParam ( call , c , arg , param , true , true ) and
4028
+ innerCallCtx = getACallCtx ( param , true , true ) and
4029
+ (
4030
+ innerCallCtx = TDataFlowCallNone ( )
4031
+ or
4032
+ innerCallCtx = TDataFlowCallSome ( call )
4033
+ )
4034
+ }
4035
+
4036
+ pragma [ nomagic]
4037
+ private predicate callEdgeArgParamCallContextReduced (
4038
+ DataFlowCall call , NodeEx arg , NodeEx param , Stage2Param:: CcCall outerCcCall ,
4039
+ DataFlowCallOption innerCallCtx
4040
+ ) {
4041
+ exists ( DataFlowCallable c |
4042
+ callEdgeArgParam ( call , c , arg , param , innerCallCtx ) and
4043
+ Stage2Param:: viableImplCallContextReduced ( call , outerCcCall ) = c
4044
+ )
4045
+ }
4046
+
4047
+ bindingset [ outerCallCtx]
4048
+ predicate callEdgeArgParam (
4049
+ NodeEx arg , NodeEx param , DataFlowCallOption outerCallCtx , DataFlowCallOption innerCallCtx
4050
+ ) {
4051
+ exists ( DataFlowCall call | callEdgeArgParam ( call , _, arg , param , innerCallCtx ) |
4052
+ outerCallCtx = TDataFlowCallNone ( )
4053
+ or
4054
+ exists ( DataFlowCall outerCall , Stage2Param:: CcCall outerCcCall |
4055
+ outerCallCtx = TDataFlowCallSome ( outerCall ) and
4056
+ outerCcCall = Stage2Param:: getCallContextCall ( outerCall , call .getEnclosingCallable ( ) )
4057
+ |
4058
+ callEdgeArgParamCallContextReduced ( call , arg , param , outerCcCall , innerCallCtx )
4059
+ or
4060
+ Stage2Param:: viableImplNotCallContextReduced ( call , outerCcCall )
4061
+ )
4062
+ )
3979
4063
}
3980
4064
3981
- predicate callEdgeReturn ( NodeEx ret , NodeEx out , boolean mayFlowThrough ) {
3982
- PrevStage:: callEdgeReturn ( _ , _, ret , _, out , true , true ) and
4065
+ predicate callEdgeReturn ( DataFlowCall call , NodeEx ret , NodeEx out , boolean mayFlowThrough ) {
4066
+ PrevStage:: callEdgeReturn ( call , _, ret , _, out , true , true ) and
3983
4067
if flowThroughOutOfCall ( ret , out ) then mayFlowThrough = true else mayFlowThrough = false
3984
4068
}
3985
4069
0 commit comments