@@ -722,7 +722,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
722
722
* the enclosing callable in order to reach a sink.
723
723
*/
724
724
pragma [ nomagic]
725
- private predicate revFlow ( NodeEx node , boolean toReturn ) {
725
+ additional predicate revFlow ( NodeEx node , boolean toReturn ) {
726
726
revFlow0 ( node , toReturn ) and
727
727
fwdFlow ( node )
728
728
}
@@ -1113,6 +1113,43 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1113
1113
result = getAdditionalFlowIntoCallNodeTerm ( arg .projectToNode ( ) , p .projectToNode ( ) )
1114
1114
}
1115
1115
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
+
1116
1153
/**
1117
1154
* Gets the amount of forward branching on the origin of a cross-call path
1118
1155
* edge in the graph of paths between sources and sinks that ignores call
@@ -1121,8 +1158,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1121
1158
pragma [ nomagic]
1122
1159
private int branch ( NodeEx n1 ) {
1123
1160
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
+ )
1126
1167
) + sum ( ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1 ( n1 , p1 ) )
1127
1168
}
1128
1169
@@ -1134,8 +1175,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1134
1175
pragma [ nomagic]
1135
1176
private int join ( NodeEx n2 ) {
1136
1177
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
+ )
1139
1184
) + sum ( ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1 ( arg2 , n2 ) )
1140
1185
}
1141
1186
@@ -1151,17 +1196,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1151
1196
DataFlowCall call , RetNodeEx ret , ReturnKindExt kind , NodeEx out , boolean allowsFieldFlow
1152
1197
) {
1153
1198
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
1157
1202
if
1158
- b . minimum ( j ) <= Config:: fieldFlowBranchLimit ( ) or
1203
+ j <= Config:: fieldFlowBranchLimit ( ) or
1159
1204
ignoreFieldFlowBranchLimit ( ret .getEnclosingCallable ( ) )
1160
1205
then allowsFieldFlow = true
1161
1206
else allowsFieldFlow = false
1162
1207
)
1163
1208
}
1164
1209
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
+
1165
1218
/**
1166
1219
* Holds if data can flow into `call` and that this step is part of a
1167
1220
* path from a source to a sink. The `allowsFieldFlow` flag indicates whether
@@ -1412,14 +1465,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1412
1465
)
1413
1466
or
1414
1467
// 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
+ )
1423
1478
)
1424
1479
or
1425
1480
// flow out of a callable
@@ -1604,7 +1659,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1604
1659
private predicate fwdFlowInCand (
1605
1660
DataFlowCall call , ArgNodeEx arg , FlowState state , Cc outercc , DataFlowCallable inner ,
1606
1661
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
1608
1663
) {
1609
1664
exists ( boolean allowsFieldFlow |
1610
1665
fwdFlowIntoArg ( arg , state , outercc , summaryCtx , argT , argAp , t , ap , emptyAp , apa , cc ) and
@@ -1614,28 +1669,32 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1614
1669
viableImplArgNotCallContextReduced ( call , arg , outercc )
1615
1670
) and
1616
1671
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
1618
1676
)
1619
1677
}
1620
1678
1621
1679
pragma [ inline]
1622
1680
private predicate fwdFlowInCandTypeFlowDisabled (
1623
1681
DataFlowCall call , ArgNodeEx arg , FlowState state , Cc outercc , DataFlowCallable inner ,
1624
1682
ParamNodeEx p , ParamNodeOption summaryCtx , TypOption argT , ApOption argAp , Typ t , Ap ap ,
1625
- ApApprox apa , boolean cc
1683
+ ApApprox apa , boolean cc , boolean allowsFlowThrough
1626
1684
) {
1627
1685
not enableTypeFlow ( ) and
1628
1686
fwdFlowInCand ( call , arg , state , outercc , inner , p , summaryCtx , argT , argAp , t , ap , _,
1629
- apa , cc )
1687
+ apa , cc , allowsFlowThrough )
1630
1688
}
1631
1689
1632
1690
pragma [ nomagic]
1633
1691
private predicate fwdFlowInCandTypeFlowEnabled (
1634
1692
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
1636
1694
) {
1637
1695
enableTypeFlow ( ) and
1638
- fwdFlowInCand ( call , arg , _, outercc , inner , p , _, _, _, _, _, emptyAp , apa , cc )
1696
+ fwdFlowInCand ( call , arg , _, outercc , inner , p , _, _, _, _, _, emptyAp , apa , cc ,
1697
+ allowsFlowThrough )
1639
1698
}
1640
1699
1641
1700
pragma [ nomagic]
@@ -1650,9 +1709,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1650
1709
pragma [ nomagic]
1651
1710
private predicate fwdFlowInValidEdgeTypeFlowEnabled (
1652
1711
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
1654
1713
) {
1655
- fwdFlowInCandTypeFlowEnabled ( call , arg , outercc , inner , p , emptyAp , apa , cc ) and
1714
+ fwdFlowInCandTypeFlowEnabled ( call , arg , outercc , inner , p , emptyAp , apa , cc ,
1715
+ allowsFlowThrough ) and
1656
1716
FwdTypeFlow:: typeFlowValidEdgeIn ( call , inner , cc ) and
1657
1717
innercc = getCallContextCall ( call , inner )
1658
1718
}
@@ -1661,19 +1721,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1661
1721
predicate fwdFlowIn (
1662
1722
DataFlowCall call , DataFlowCallable inner , ParamNodeEx p , FlowState state , Cc outercc ,
1663
1723
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
1665
1725
) {
1666
1726
exists ( ArgNodeEx arg |
1667
1727
// type flow disabled: linear recursion
1668
1728
fwdFlowInCandTypeFlowDisabled ( call , arg , state , outercc , inner , p , summaryCtx , argT ,
1669
- argAp , t , ap , apa , cc ) and
1729
+ argAp , t , ap , apa , cc , allowsFlowThrough ) and
1670
1730
fwdFlowInValidEdgeTypeFlowDisabled ( call , inner , innercc , pragma [ only_bind_into ] ( cc ) )
1671
1731
or
1672
1732
// type flow enabled: non-linear recursion
1673
1733
exists ( boolean emptyAp |
1674
1734
fwdFlowIntoArg ( arg , state , outercc , summaryCtx , argT , argAp , t , ap , emptyAp , apa , cc ) and
1675
1735
fwdFlowInValidEdgeTypeFlowEnabled ( call , arg , outercc , inner , p , innercc , emptyAp ,
1676
- apa , cc )
1736
+ apa , cc , allowsFlowThrough )
1677
1737
)
1678
1738
)
1679
1739
}
@@ -1683,10 +1743,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1683
1743
1684
1744
pragma [ nomagic]
1685
1745
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
1687
1748
) {
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
+ )
1690
1756
}
1691
1757
1692
1758
pragma [ nomagic]
@@ -1784,7 +1850,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1784
1850
Typ t , Ap ap , boolean cc
1785
1851
) {
1786
1852
FwdFlowIn< FwdFlowInNoRestriction > :: fwdFlowIn ( call , c , p , state , _, innercc , _, _, _, t ,
1787
- ap , _, cc )
1853
+ ap , _, cc , _ )
1788
1854
}
1789
1855
1790
1856
pragma [ nomagic]
@@ -1903,7 +1969,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
1903
1969
ApOption argAp , ParamNodeEx p , Typ t , Ap ap
1904
1970
) {
1905
1971
FwdFlowIn< FwdFlowThroughRestriction > :: fwdFlowIn ( call , _, p , _, cc , innerCc , summaryCtx ,
1906
- argT , argAp , t , ap , _, _)
1972
+ argT , argAp , t , ap , _, _, true )
1907
1973
}
1908
1974
1909
1975
pragma [ nomagic]
0 commit comments