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