@@ -722,7 +722,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
722722 * the enclosing callable in order to reach a sink.
723723 */
724724 pragma [ nomagic]
725- private predicate revFlow ( NodeEx node , boolean toReturn ) {
725+ additional predicate revFlow ( NodeEx node , boolean toReturn ) {
726726 revFlow0 ( node , toReturn ) and
727727 fwdFlow ( node )
728728 }
@@ -1113,6 +1113,43 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11131113 result = getAdditionalFlowIntoCallNodeTerm ( arg .projectToNode ( ) , p .projectToNode ( ) )
11141114 }
11151115
1116+ pragma [ nomagic]
1117+ private predicate returnCallEdge1 ( DataFlowCallable c , DataFlowCall call , NodeEx out ) {
1118+ exists ( RetNodeEx ret |
1119+ flowOutOfCallNodeCand1 ( call , ret , _, out ) and c = ret .getEnclosingCallable ( )
1120+ )
1121+ }
1122+
1123+ private int simpleDispatchFanoutOnReturn ( DataFlowCall call , NodeEx out ) {
1124+ result = strictcount ( DataFlowCallable c | returnCallEdge1 ( c , call , out ) )
1125+ }
1126+
1127+ private int ctxDispatchFanoutOnReturn ( NodeEx out , DataFlowCall ctx ) {
1128+ exists ( DataFlowCall call , DataFlowCallable c |
1129+ simpleDispatchFanoutOnReturn ( call , out ) > 1 and
1130+ not Stage1:: revFlow ( out , false ) and
1131+ call .getEnclosingCallable ( ) = c and
1132+ returnCallEdge1 ( c , ctx , _) and
1133+ mayBenefitFromCallContextExt ( call , _) and
1134+ result =
1135+ count ( DataFlowCallable tgt |
1136+ tgt = viableImplInCallContextExt ( call , ctx ) and
1137+ returnCallEdge1 ( tgt , call , out )
1138+ )
1139+ )
1140+ }
1141+
1142+ private int ctxDispatchFanoutOnReturn ( NodeEx out ) {
1143+ result = max ( DataFlowCall ctx | | ctxDispatchFanoutOnReturn ( out , ctx ) )
1144+ }
1145+
1146+ private int dispatchFanoutOnReturn ( NodeEx out ) {
1147+ result = ctxDispatchFanoutOnReturn ( out )
1148+ or
1149+ not exists ( ctxDispatchFanoutOnReturn ( out ) ) and
1150+ result = simpleDispatchFanoutOnReturn ( _, out )
1151+ }
1152+
11161153 /**
11171154 * Gets the amount of forward branching on the origin of a cross-call path
11181155 * edge in the graph of paths between sources and sinks that ignores call
@@ -1121,8 +1158,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11211158 pragma [ nomagic]
11221159 private int branch ( NodeEx n1 ) {
11231160 result =
1124- strictcount ( NodeEx n |
1125- flowOutOfCallNodeCand1 ( _, n1 , _, n ) or flowIntoCallNodeCand1 ( _, n1 , n )
1161+ strictcount ( DataFlowCallable c |
1162+ exists ( NodeEx n |
1163+ flowOutOfCallNodeCand1 ( _, n1 , _, n ) or flowIntoCallNodeCand1 ( _, n1 , n )
1164+ |
1165+ c = n .getEnclosingCallable ( )
1166+ )
11261167 ) + sum ( ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1 ( n1 , p1 ) )
11271168 }
11281169
@@ -1134,8 +1175,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11341175 pragma [ nomagic]
11351176 private int join ( NodeEx n2 ) {
11361177 result =
1137- strictcount ( NodeEx n |
1138- flowOutOfCallNodeCand1 ( _, n , _, n2 ) or flowIntoCallNodeCand1 ( _, n , n2 )
1178+ strictcount ( DataFlowCallable c |
1179+ exists ( NodeEx n |
1180+ flowOutOfCallNodeCand1 ( _, n , _, n2 ) or flowIntoCallNodeCand1 ( _, n , n2 )
1181+ |
1182+ c = n .getEnclosingCallable ( )
1183+ )
11391184 ) + sum ( ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1 ( arg2 , n2 ) )
11401185 }
11411186
@@ -1151,17 +1196,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11511196 DataFlowCall call , RetNodeEx ret , ReturnKindExt kind , NodeEx out , boolean allowsFieldFlow
11521197 ) {
11531198 flowOutOfCallNodeCand1 ( call , ret , kind , out ) and
1154- exists ( int b , int j |
1155- b = branch ( ret ) and
1156- j = join ( out ) and
1199+ exists ( int j |
1200+ j = dispatchFanoutOnReturn ( out ) and
1201+ j > 0 and
11571202 if
1158- b . minimum ( j ) <= Config:: fieldFlowBranchLimit ( ) or
1203+ j <= Config:: fieldFlowBranchLimit ( ) or
11591204 ignoreFieldFlowBranchLimit ( ret .getEnclosingCallable ( ) )
11601205 then allowsFieldFlow = true
11611206 else allowsFieldFlow = false
11621207 )
11631208 }
11641209
1210+ pragma [ nomagic]
1211+ private predicate allowsFieldFlowThrough ( DataFlowCall call , DataFlowCallable c ) {
1212+ exists ( RetNodeEx ret |
1213+ flowOutOfCallNodeCand1 ( call , ret , _, _, true ) and
1214+ c = ret .getEnclosingCallable ( )
1215+ )
1216+ }
1217+
11651218 /**
11661219 * Holds if data can flow into `call` and that this step is part of a
11671220 * path from a source to a sink. The `allowsFieldFlow` flag indicates whether
@@ -1412,14 +1465,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
14121465 )
14131466 or
14141467 // flow into a callable
1415- fwdFlowIn ( node , apa , state , cc , t , ap ) and
1416- if PrevStage:: parameterMayFlowThrough ( node , apa )
1417- then (
1418- summaryCtx = TParamNodeSome ( node .asNode ( ) ) and
1419- argT = TypOption:: some ( t ) and
1420- argAp = apSome ( ap )
1421- ) else (
1422- summaryCtx = TParamNodeNone ( ) and argT instanceof TypOption:: None and argAp = apNone ( )
1468+ exists ( boolean allowsFlowThrough |
1469+ fwdFlowIn ( node , apa , state , cc , t , ap , allowsFlowThrough ) and
1470+ if allowsFlowThrough = true
1471+ then (
1472+ summaryCtx = TParamNodeSome ( node .asNode ( ) ) and
1473+ argT = TypOption:: some ( t ) and
1474+ argAp = apSome ( ap )
1475+ ) else (
1476+ summaryCtx = TParamNodeNone ( ) and argT instanceof TypOption:: None and argAp = apNone ( )
1477+ )
14231478 )
14241479 or
14251480 // flow out of a callable
@@ -1604,7 +1659,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
16041659 private predicate fwdFlowInCand (
16051660 DataFlowCall call , ArgNodeEx arg , FlowState state , Cc outercc , DataFlowCallable inner ,
16061661 ParamNodeEx p , ParamNodeOption summaryCtx , TypOption argT , ApOption argAp , Typ t , Ap ap ,
1607- boolean emptyAp , ApApprox apa , boolean cc
1662+ boolean emptyAp , ApApprox apa , boolean cc , boolean allowsFlowThrough
16081663 ) {
16091664 exists ( boolean allowsFieldFlow |
16101665 fwdFlowIntoArg ( arg , state , outercc , summaryCtx , argT , argAp , t , ap , emptyAp , apa , cc ) and
@@ -1614,28 +1669,32 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
16141669 viableImplArgNotCallContextReduced ( call , arg , outercc )
16151670 ) and
16161671 callEdgeArgParamRestrictedInlineLate ( call , inner , arg , p , allowsFieldFlow , apa ) and
1617- if allowsFieldFlow = false then emptyAp = true else any ( )
1672+ ( if allowsFieldFlow = false then emptyAp = true else any ( ) ) and
1673+ if allowsFieldFlowThrough ( call , inner )
1674+ then allowsFlowThrough = true
1675+ else allowsFlowThrough = emptyAp
16181676 )
16191677 }
16201678
16211679 pragma [ inline]
16221680 private predicate fwdFlowInCandTypeFlowDisabled (
16231681 DataFlowCall call , ArgNodeEx arg , FlowState state , Cc outercc , DataFlowCallable inner ,
16241682 ParamNodeEx p , ParamNodeOption summaryCtx , TypOption argT , ApOption argAp , Typ t , Ap ap ,
1625- ApApprox apa , boolean cc
1683+ ApApprox apa , boolean cc , boolean allowsFlowThrough
16261684 ) {
16271685 not enableTypeFlow ( ) and
16281686 fwdFlowInCand ( call , arg , state , outercc , inner , p , summaryCtx , argT , argAp , t , ap , _,
1629- apa , cc )
1687+ apa , cc , allowsFlowThrough )
16301688 }
16311689
16321690 pragma [ nomagic]
16331691 private predicate fwdFlowInCandTypeFlowEnabled (
16341692 DataFlowCall call , ArgNodeEx arg , Cc outercc , DataFlowCallable inner , ParamNodeEx p ,
1635- boolean emptyAp , ApApprox apa , boolean cc
1693+ boolean emptyAp , ApApprox apa , boolean cc , boolean allowsFlowThrough
16361694 ) {
16371695 enableTypeFlow ( ) and
1638- fwdFlowInCand ( call , arg , _, outercc , inner , p , _, _, _, _, _, emptyAp , apa , cc )
1696+ fwdFlowInCand ( call , arg , _, outercc , inner , p , _, _, _, _, _, emptyAp , apa , cc ,
1697+ allowsFlowThrough )
16391698 }
16401699
16411700 pragma [ nomagic]
@@ -1650,9 +1709,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
16501709 pragma [ nomagic]
16511710 private predicate fwdFlowInValidEdgeTypeFlowEnabled (
16521711 DataFlowCall call , ArgNodeEx arg , Cc outercc , DataFlowCallable inner , ParamNodeEx p ,
1653- CcCall innercc , boolean emptyAp , ApApprox apa , boolean cc
1712+ CcCall innercc , boolean emptyAp , ApApprox apa , boolean cc , boolean allowsFlowThrough
16541713 ) {
1655- fwdFlowInCandTypeFlowEnabled ( call , arg , outercc , inner , p , emptyAp , apa , cc ) and
1714+ fwdFlowInCandTypeFlowEnabled ( call , arg , outercc , inner , p , emptyAp , apa , cc ,
1715+ allowsFlowThrough ) and
16561716 FwdTypeFlow:: typeFlowValidEdgeIn ( call , inner , cc ) and
16571717 innercc = getCallContextCall ( call , inner )
16581718 }
@@ -1661,19 +1721,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
16611721 predicate fwdFlowIn (
16621722 DataFlowCall call , DataFlowCallable inner , ParamNodeEx p , FlowState state , Cc outercc ,
16631723 CcCall innercc , ParamNodeOption summaryCtx , TypOption argT , ApOption argAp , Typ t ,
1664- Ap ap , ApApprox apa , boolean cc
1724+ Ap ap , ApApprox apa , boolean cc , boolean allowsFlowThrough
16651725 ) {
16661726 exists ( ArgNodeEx arg |
16671727 // type flow disabled: linear recursion
16681728 fwdFlowInCandTypeFlowDisabled ( call , arg , state , outercc , inner , p , summaryCtx , argT ,
1669- argAp , t , ap , apa , cc ) and
1729+ argAp , t , ap , apa , cc , allowsFlowThrough ) and
16701730 fwdFlowInValidEdgeTypeFlowDisabled ( call , inner , innercc , pragma [ only_bind_into ] ( cc ) )
16711731 or
16721732 // type flow enabled: non-linear recursion
16731733 exists ( boolean emptyAp |
16741734 fwdFlowIntoArg ( arg , state , outercc , summaryCtx , argT , argAp , t , ap , emptyAp , apa , cc ) and
16751735 fwdFlowInValidEdgeTypeFlowEnabled ( call , arg , outercc , inner , p , innercc , emptyAp ,
1676- apa , cc )
1736+ apa , cc , allowsFlowThrough )
16771737 )
16781738 )
16791739 }
@@ -1683,10 +1743,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
16831743
16841744 pragma [ nomagic]
16851745 private predicate fwdFlowIn (
1686- ParamNodeEx p , ApApprox apa , FlowState state , CcCall innercc , Typ t , Ap ap
1746+ ParamNodeEx p , ApApprox apa , FlowState state , CcCall innercc , Typ t , Ap ap ,
1747+ boolean allowsFlowThrough
16871748 ) {
1688- FwdFlowIn< FwdFlowInNoRestriction > :: fwdFlowIn ( _, _, p , state , _, innercc , _, _, _, t , ap ,
1689- apa , _)
1749+ exists ( boolean allowsFlowThrough0 |
1750+ FwdFlowIn< FwdFlowInNoRestriction > :: fwdFlowIn ( _, _, p , state , _, innercc , _, _, _, t , ap ,
1751+ apa , _, allowsFlowThrough0 ) and
1752+ if PrevStage:: parameterMayFlowThrough ( p , apa )
1753+ then allowsFlowThrough = allowsFlowThrough0
1754+ else allowsFlowThrough = false
1755+ )
16901756 }
16911757
16921758 pragma [ nomagic]
@@ -1784,7 +1850,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
17841850 Typ t , Ap ap , boolean cc
17851851 ) {
17861852 FwdFlowIn< FwdFlowInNoRestriction > :: fwdFlowIn ( call , c , p , state , _, innercc , _, _, _, t ,
1787- ap , _, cc )
1853+ ap , _, cc , _ )
17881854 }
17891855
17901856 pragma [ nomagic]
@@ -1903,7 +1969,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
19031969 ApOption argAp , ParamNodeEx p , Typ t , Ap ap
19041970 ) {
19051971 FwdFlowIn< FwdFlowThroughRestriction > :: fwdFlowIn ( call , _, p , _, cc , innerCc , summaryCtx ,
1906- argT , argAp , t , ap , _, _)
1972+ argT , argAp , t , ap , _, _, true )
19071973 }
19081974
19091975 pragma [ nomagic]
0 commit comments