Skip to content

Commit 12d1d04

Browse files
authored
Merge pull request github#13983 from hvitved/dataflow/reduced-dispatch-early-join
Data flow: Earlier call-context based dispatch filtering
2 parents 2d0f73d + 1b4520b commit 12d1d04

File tree

2 files changed

+221
-111
lines changed

2 files changed

+221
-111
lines changed

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

Lines changed: 190 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ module MakeImpl<InputSig Lang> {
190190

191191
private class ArgNodeEx extends NodeEx {
192192
ArgNodeEx() { this.asNode() instanceof ArgNode }
193+
194+
DataFlowCall getCall() { this.asNode().(ArgNode).argumentOf(result, _) }
193195
}
194196

195197
private class ParamNodeEx extends NodeEx {
@@ -1145,11 +1147,20 @@ module MakeImpl<InputSig Lang> {
11451147

11461148
class LocalCc;
11471149

1148-
bindingset[call, c, outercc]
1149-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc);
1150+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx);
1151+
1152+
bindingset[call, ctx]
1153+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx);
1154+
1155+
bindingset[call, c]
1156+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c);
11501157

1151-
bindingset[call, c, innercc]
1152-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc);
1158+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx);
1159+
1160+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx);
1161+
1162+
bindingset[call, c]
1163+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call);
11531164

11541165
bindingset[node, cc]
11551166
LocalCc getLocalCc(NodeEx node, Cc cc);
@@ -1191,21 +1202,24 @@ module MakeImpl<InputSig Lang> {
11911202

11921203
pragma[nomagic]
11931204
private predicate flowIntoCallApa(
1194-
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
1205+
DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p,
1206+
boolean allowsFieldFlow, ApApprox apa
11951207
) {
11961208
flowIntoCall(call, arg, p, allowsFieldFlow) and
11971209
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and
1198-
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa))
1210+
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa)) and
1211+
c = p.getEnclosingCallable()
11991212
}
12001213

12011214
pragma[nomagic]
12021215
private predicate flowOutOfCallApa(
1203-
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
1204-
ApApprox apa
1216+
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, ReturnKindExt kind, NodeEx out,
1217+
boolean allowsFieldFlow, ApApprox apa
12051218
) {
12061219
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
12071220
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and
1208-
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa))
1221+
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa)) and
1222+
c = ret.getEnclosingCallable()
12091223
}
12101224

12111225
pragma[nomagic]
@@ -1214,7 +1228,7 @@ module MakeImpl<InputSig Lang> {
12141228
ApApprox argApa, ApApprox apa
12151229
) {
12161230
exists(ReturnKindExt kind |
1217-
flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and
1231+
flowOutOfCallApa(call, _, ret, kind, out, allowsFieldFlow, apa) and
12181232
PrevStage::callMayFlowThroughRev(call) and
12191233
PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and
12201234
matchesCall(ccc, call)
@@ -1332,16 +1346,7 @@ module MakeImpl<InputSig Lang> {
13321346
)
13331347
or
13341348
// flow out of a callable
1335-
exists(
1336-
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
1337-
DataFlowCallable inner
1338-
|
1339-
fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and
1340-
flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and
1341-
inner = ret.getEnclosingCallable() and
1342-
cc = getCallContextReturn(inner, call, innercc) and
1343-
if allowsFieldFlow = false then ap instanceof ApNil else any()
1344-
)
1349+
fwdFlowOut(node, state, cc, summaryCtx, argT, argAp, t, ap, apa)
13451350
or
13461351
// flow through a callable
13471352
exists(
@@ -1408,15 +1413,115 @@ module MakeImpl<InputSig Lang> {
14081413
)
14091414
}
14101415

1416+
bindingset[call, ctx]
1417+
pragma[inline_late]
1418+
private DataFlowCallable viableImplCallContextReducedInlineLate(
1419+
DataFlowCall call, CcCall ctx
1420+
) {
1421+
result = viableImplCallContextReduced(call, ctx)
1422+
}
1423+
1424+
bindingset[arg, ctx]
1425+
pragma[inline_late]
1426+
private DataFlowCallable viableImplCallContextReducedInlineLate(
1427+
DataFlowCall call, ArgNodeEx arg, CcCall ctx
1428+
) {
1429+
call = arg.getCall() and
1430+
result = viableImplCallContextReducedInlineLate(call, ctx)
1431+
}
1432+
1433+
bindingset[call]
1434+
pragma[inline_late]
1435+
private predicate flowIntoCallApaInlineLate(
1436+
DataFlowCall call, DataFlowCallable c, ArgNodeEx arg, ParamNodeEx p,
1437+
boolean allowsFieldFlow, ApApprox apa
1438+
) {
1439+
flowIntoCallApa(call, c, arg, p, allowsFieldFlow, apa)
1440+
}
1441+
1442+
bindingset[call, ctx]
1443+
pragma[inline_late]
1444+
private predicate viableImplNotCallContextReducedInlineLate(DataFlowCall call, Cc ctx) {
1445+
viableImplNotCallContextReduced(call, ctx)
1446+
}
1447+
1448+
bindingset[arg, outercc]
1449+
pragma[inline_late]
1450+
private predicate viableImplArgNotCallContextReduced(
1451+
DataFlowCall call, ArgNodeEx arg, Cc outercc
1452+
) {
1453+
call = arg.getCall() and
1454+
viableImplNotCallContextReducedInlineLate(call, outercc)
1455+
}
1456+
14111457
pragma[nomagic]
14121458
private predicate fwdFlowIn(
14131459
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc,
14141460
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
14151461
) {
1416-
exists(ArgNodeEx arg, boolean allowsFieldFlow |
1462+
exists(ArgNodeEx arg, boolean allowsFieldFlow, DataFlowCallable inner |
14171463
fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1418-
flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and
1419-
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
1464+
(
1465+
inner = viableImplCallContextReducedInlineLate(call, arg, outercc)
1466+
or
1467+
viableImplArgNotCallContextReduced(call, arg, outercc)
1468+
) and
1469+
flowIntoCallApaInlineLate(call, inner, arg, p, allowsFieldFlow, apa)
1470+
|
1471+
innercc = getCallContextCall(call, inner) and
1472+
if allowsFieldFlow = false then ap instanceof ApNil else any()
1473+
)
1474+
}
1475+
1476+
bindingset[ctx, result]
1477+
pragma[inline_late]
1478+
private DataFlowCallable viableImplCallContextReducedReverseInlineLate(
1479+
DataFlowCall call, CcNoCall ctx
1480+
) {
1481+
result = viableImplCallContextReducedReverse(call, ctx)
1482+
}
1483+
1484+
bindingset[call]
1485+
pragma[inline_late]
1486+
private predicate flowOutOfCallApaInlineLate(
1487+
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
1488+
ApApprox apa
1489+
) {
1490+
flowOutOfCallApa(call, c, ret, _, out, allowsFieldFlow, apa)
1491+
}
1492+
1493+
bindingset[c, ret, apa, innercc]
1494+
pragma[inline_late]
1495+
pragma[noopt]
1496+
private predicate flowOutOfCallApaNotCallContextReduced(
1497+
DataFlowCall call, DataFlowCallable c, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
1498+
ApApprox apa, CcNoCall innercc
1499+
) {
1500+
viableImplNotCallContextReducedReverse(innercc) and
1501+
flowOutOfCallApa(call, c, ret, _, out, allowsFieldFlow, apa)
1502+
}
1503+
1504+
// inline to reduce number of iterations
1505+
pragma[inline]
1506+
private predicate fwdFlowOut(
1507+
NodeEx out, FlowState state, CcNoCall outercc, ParamNodeOption summaryCtx, TypOption argT,
1508+
ApOption argAp, Typ t, Ap ap, ApApprox apa
1509+
) {
1510+
exists(
1511+
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
1512+
DataFlowCallable inner
1513+
|
1514+
fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and
1515+
inner = ret.getEnclosingCallable() and
1516+
(
1517+
inner = viableImplCallContextReducedReverseInlineLate(call, innercc) and
1518+
flowOutOfCallApaInlineLate(call, inner, ret, out, allowsFieldFlow, apa)
1519+
or
1520+
flowOutOfCallApaNotCallContextReduced(call, inner, ret, out, allowsFieldFlow, apa,
1521+
innercc)
1522+
)
1523+
|
1524+
outercc = getCallContextReturn(inner, call) and
14201525
if allowsFieldFlow = false then ap instanceof ApNil else any()
14211526
)
14221527
}
@@ -1518,7 +1623,7 @@ module MakeImpl<InputSig Lang> {
15181623
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap
15191624
) {
15201625
exists(ApApprox argApa, Typ argT |
1521-
flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p),
1626+
flowIntoCallApa(call, _, pragma[only_bind_into](arg), pragma[only_bind_into](p),
15221627
allowsFieldFlow, argApa) and
15231628
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp),
15241629
argApa) and
@@ -1529,24 +1634,23 @@ module MakeImpl<InputSig Lang> {
15291634
}
15301635

15311636
pragma[nomagic]
1532-
private predicate flowIntoCallAp(
1533-
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap
1534-
) {
1535-
exists(ApApprox apa |
1536-
flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and
1537-
fwdFlow(arg, _, _, _, _, _, _, ap, apa)
1637+
private predicate flowIntoCallAp(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Ap ap) {
1638+
exists(ApApprox apa, boolean allowsFieldFlow |
1639+
flowIntoCallApa(call, _, arg, p, allowsFieldFlow, apa) and
1640+
fwdFlow(arg, _, _, _, _, _, _, ap, apa) and
1641+
if allowsFieldFlow = false then ap instanceof ApNil else any()
15381642
)
15391643
}
15401644

15411645
pragma[nomagic]
15421646
private predicate flowOutOfCallAp(
1543-
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
1544-
Ap ap
1647+
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Ap ap
15451648
) {
1546-
exists(ApApprox apa |
1547-
flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and
1649+
exists(ApApprox apa, boolean allowsFieldFlow |
1650+
flowOutOfCallApa(call, _, ret, _, out, allowsFieldFlow, apa) and
15481651
fwdFlow(ret, _, _, _, _, _, _, ap, apa) and
1549-
pos = ret.getReturnPosition()
1652+
pos = ret.getReturnPosition() and
1653+
if allowsFieldFlow = false then ap instanceof ApNil else any()
15501654
)
15511655
}
15521656

@@ -1627,10 +1731,9 @@ module MakeImpl<InputSig Lang> {
16271731
)
16281732
or
16291733
// flow into a callable
1630-
exists(ParamNodeEx p, boolean allowsFieldFlow |
1734+
exists(ParamNodeEx p |
16311735
revFlow(p, state, TReturnCtxNone(), returnAp, ap) and
1632-
flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and
1633-
(if allowsFieldFlow = false then ap instanceof ApNil else any()) and
1736+
flowIntoCallAp(_, node, p, ap) and
16341737
returnCtx = TReturnCtxNone()
16351738
)
16361739
or
@@ -1680,10 +1783,9 @@ module MakeImpl<InputSig Lang> {
16801783
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state,
16811784
ReturnCtx returnCtx, ApOption returnAp, Ap ap
16821785
) {
1683-
exists(NodeEx out, boolean allowsFieldFlow |
1786+
exists(NodeEx out |
16841787
revFlow(out, state, returnCtx, returnAp, ap) and
1685-
flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and
1686-
if allowsFieldFlow = false then ap instanceof ApNil else any()
1788+
flowOutOfCallAp(call, ret, pos, out, ap)
16871789
)
16881790
}
16891791

@@ -1872,11 +1974,22 @@ module MakeImpl<InputSig Lang> {
18721974
bindingset[node, cc]
18731975
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
18741976

1875-
bindingset[call, c, outercc]
1876-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
1977+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) { none() }
1978+
1979+
bindingset[call, ctx]
1980+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) { any() }
1981+
1982+
bindingset[call, c]
1983+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) { any() }
18771984

1878-
bindingset[call, c, innercc]
1879-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
1985+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
1986+
none()
1987+
}
1988+
1989+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) { any() }
1990+
1991+
bindingset[call, c]
1992+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
18801993
}
18811994

18821995
private module Level1CallContext {
@@ -1899,9 +2012,17 @@ module MakeImpl<InputSig Lang> {
18992012
bindingset[node, cc]
19002013
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
19012014

1902-
bindingset[call, c, outercc]
1903-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
1904-
checkCallContextCall(outercc, call, c) and
2015+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
2016+
result = prunedViableImplInCallContext(call, ctx)
2017+
}
2018+
2019+
bindingset[call, ctx]
2020+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
2021+
noPrunedViableImplInCallContext(call, ctx)
2022+
}
2023+
2024+
bindingset[call, c]
2025+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
19052026
if recordDataFlowCallSiteDispatch(call, c)
19062027
then result = TSpecificCall(call)
19072028
else result = TSomeCall()
@@ -1918,18 +2039,33 @@ module MakeImpl<InputSig Lang> {
19182039
node.getEnclosingCallable())
19192040
}
19202041

1921-
bindingset[call, c, outercc]
1922-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
1923-
checkCallContextCall(outercc, call, c) and
2042+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
2043+
result = prunedViableImplInCallContext(call, ctx)
2044+
}
2045+
2046+
bindingset[call, ctx]
2047+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
2048+
noPrunedViableImplInCallContext(call, ctx)
2049+
}
2050+
2051+
bindingset[call, c]
2052+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
19242053
if recordDataFlowCallSite(call, c)
19252054
then result = TSpecificCall(call)
19262055
else result = TSomeCall()
19272056
}
19282057
}
19292058

1930-
bindingset[call, c, innercc]
1931-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
1932-
checkCallContextReturn(innercc, c, call) and
2059+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
2060+
call = prunedViableImplInCallContextReverse(result, ctx)
2061+
}
2062+
2063+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) {
2064+
ctx instanceof CallContextAny
2065+
}
2066+
2067+
bindingset[call, c]
2068+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
19332069
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
19342070
}
19352071
}

0 commit comments

Comments
 (0)