Skip to content

Commit 82afbbc

Browse files
committed
Dataflow: Adjust fieldFlowBranchLimit count (block less) and adjust return edge condition (block more)
1 parent a99849d commit 82afbbc

File tree

1 file changed

+99
-33
lines changed

1 file changed

+99
-33
lines changed

shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll

Lines changed: 99 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)