Skip to content

Commit 570654d

Browse files
committed
Data flow: Earlier call-context based dispatch filtering
1 parent 44b734e commit 570654d

File tree

2 files changed

+199
-104
lines changed

2 files changed

+199
-104
lines changed

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

Lines changed: 175 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,11 +1145,21 @@ module MakeImpl<InputSig Lang> {
11451145

11461146
class LocalCc;
11471147

1148-
bindingset[call, c, outercc]
1149-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc);
1148+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx);
11501149

1151-
bindingset[call, c, innercc]
1152-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc);
1150+
bindingset[call, ctx]
1151+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx);
1152+
1153+
bindingset[call, c]
1154+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c);
1155+
1156+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx);
1157+
1158+
bindingset[ctx]
1159+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx);
1160+
1161+
bindingset[call, c]
1162+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call);
11531163

11541164
bindingset[node, cc]
11551165
LocalCc getLocalCc(NodeEx node, Cc cc);
@@ -1191,21 +1201,24 @@ module MakeImpl<InputSig Lang> {
11911201

11921202
pragma[nomagic]
11931203
private predicate flowIntoCallApa(
1194-
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa
1204+
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, DataFlowCallable c,
1205+
boolean allowsFieldFlow, ApApprox apa
11951206
) {
11961207
flowIntoCall(call, arg, p, allowsFieldFlow) and
11971208
PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and
1198-
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa))
1209+
PrevStage::revFlowAp(arg, pragma[only_bind_into](apa)) and
1210+
c = p.getEnclosingCallable()
11991211
}
12001212

12011213
pragma[nomagic]
12021214
private predicate flowOutOfCallApa(
1203-
DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow,
1204-
ApApprox apa
1215+
DataFlowCall call, RetNodeEx ret, DataFlowCallable c, ReturnKindExt kind, NodeEx out,
1216+
boolean allowsFieldFlow, ApApprox apa
12051217
) {
12061218
flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and
12071219
PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and
1208-
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa))
1220+
PrevStage::revFlowAp(ret, pragma[only_bind_into](apa)) and
1221+
c = ret.getEnclosingCallable()
12091222
}
12101223

12111224
pragma[nomagic]
@@ -1214,7 +1227,7 @@ module MakeImpl<InputSig Lang> {
12141227
ApApprox argApa, ApApprox apa
12151228
) {
12161229
exists(ReturnKindExt kind |
1217-
flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and
1230+
flowOutOfCallApa(call, ret, _, kind, out, allowsFieldFlow, apa) and
12181231
PrevStage::callMayFlowThroughRev(call) and
12191232
PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and
12201233
matchesCall(ccc, call)
@@ -1332,16 +1345,7 @@ module MakeImpl<InputSig Lang> {
13321345
)
13331346
or
13341347
// 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-
)
1348+
fwdFlowOut(node, state, cc, summaryCtx, argT, argAp, t, ap, apa)
13451349
or
13461350
// flow through a callable
13471351
exists(
@@ -1408,15 +1412,98 @@ module MakeImpl<InputSig Lang> {
14081412
)
14091413
}
14101414

1415+
pragma[nomagic]
1416+
private predicate fwdFlowIn0(
1417+
DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, ParamNodeOption summaryCtx,
1418+
TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
1419+
) {
1420+
fwdFlow(arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1421+
flowIntoCallApa(call, arg, _, _, _, _)
1422+
}
1423+
1424+
pragma[nomagic]
1425+
private predicate fwdFlowInCallContextReduced(
1426+
DataFlowCall call, ArgNodeEx arg, FlowState state, CcCall outercc,
1427+
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa,
1428+
DataFlowCallable inner
1429+
) {
1430+
fwdFlowIn0(call, arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1431+
inner = viableImplCallContextReduced(call, outercc)
1432+
}
1433+
1434+
pragma[nomagic]
1435+
private predicate fwdFlowInNotCallContextReduced(
1436+
DataFlowCall call, ArgNodeEx arg, FlowState state, Cc outercc, ParamNodeOption summaryCtx,
1437+
TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
1438+
) {
1439+
fwdFlowIn0(call, arg, state, outercc, summaryCtx, argT, argAp, t, ap, apa) and
1440+
viableImplNotCallContextReduced(call, outercc)
1441+
}
1442+
14111443
pragma[nomagic]
14121444
private predicate fwdFlowIn(
14131445
DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc,
14141446
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa
14151447
) {
1416-
exists(ArgNodeEx arg, boolean allowsFieldFlow |
1417-
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
1448+
exists(ArgNodeEx arg, boolean allowsFieldFlow, DataFlowCallable inner |
1449+
fwdFlowInCallContextReduced(call, arg, state, outercc, summaryCtx, argT, argAp, t, ap,
1450+
apa, inner)
1451+
or
1452+
fwdFlowInNotCallContextReduced(call, arg, state, outercc, summaryCtx, argT, argAp, t,
1453+
ap, apa)
1454+
|
1455+
flowIntoCallApa(call, arg, p, inner, allowsFieldFlow, apa) and
1456+
innercc = getCallContextCall(call, inner) and
1457+
if allowsFieldFlow = false then ap instanceof ApNil else any()
1458+
)
1459+
}
1460+
1461+
pragma[nomagic]
1462+
private predicate fwdFlowOut0(
1463+
RetNodeEx ret, FlowState state, CcNoCall innercc, ParamNodeOption summaryCtx,
1464+
TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, DataFlowCallable inner
1465+
) {
1466+
fwdFlow(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa) and
1467+
inner = ret.getEnclosingCallable()
1468+
}
1469+
1470+
pragma[nomagic]
1471+
private predicate fwdFlowOutCallContextReduced(
1472+
DataFlowCall call, RetNodeEx ret, FlowState state, CcNoCall innercc,
1473+
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa,
1474+
DataFlowCallable inner
1475+
) {
1476+
fwdFlowOut0(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa, inner) and
1477+
inner = viableImplCallContextReducedReverse(call, innercc)
1478+
}
1479+
1480+
pragma[nomagic]
1481+
private predicate fwdFlowOutNotCallContextReduced(
1482+
RetNodeEx ret, FlowState state, CcNoCall innercc, ParamNodeOption summaryCtx,
1483+
TypOption argT, ApOption argAp, Typ t, Ap ap, ApApprox apa, DataFlowCallable inner
1484+
) {
1485+
fwdFlowOut0(ret, state, innercc, summaryCtx, argT, argAp, t, ap, apa, inner) and
1486+
viableImplNotCallContextReducedReverse(innercc)
1487+
}
1488+
1489+
// inline to reduce number of iterations
1490+
pragma[inline]
1491+
private predicate fwdFlowOut(
1492+
NodeEx out, FlowState state, CcNoCall outercc, ParamNodeOption summaryCtx, TypOption argT,
1493+
ApOption argAp, Typ t, Ap ap, ApApprox apa
1494+
) {
1495+
exists(
1496+
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
1497+
DataFlowCallable inner
1498+
|
1499+
fwdFlowOutCallContextReduced(call, ret, state, innercc, summaryCtx, argT, argAp, t, ap,
1500+
apa, inner)
1501+
or
1502+
fwdFlowOutNotCallContextReduced(ret, state, innercc, summaryCtx, argT, argAp, t, ap,
1503+
apa, inner)
1504+
|
1505+
flowOutOfCallApa(call, ret, inner, _, out, allowsFieldFlow, apa) and
1506+
outercc = getCallContextReturn(inner, call) and
14201507
if allowsFieldFlow = false then ap instanceof ApNil else any()
14211508
)
14221509
}
@@ -1518,7 +1605,7 @@ module MakeImpl<InputSig Lang> {
15181605
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap
15191606
) {
15201607
exists(ApApprox argApa, Typ argT |
1521-
flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p),
1608+
flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), _,
15221609
allowsFieldFlow, argApa) and
15231610
fwdFlow(arg, _, _, _, _, _, pragma[only_bind_into](argT), pragma[only_bind_into](argAp),
15241611
argApa) and
@@ -1529,24 +1616,23 @@ module MakeImpl<InputSig Lang> {
15291616
}
15301617

15311618
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)
1619+
private predicate flowIntoCallAp(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Ap ap) {
1620+
exists(ApApprox apa, boolean allowsFieldFlow |
1621+
flowIntoCallApa(call, arg, p, _, allowsFieldFlow, apa) and
1622+
fwdFlow(arg, _, _, _, _, _, _, ap, apa) and
1623+
if allowsFieldFlow = false then ap instanceof ApNil else any()
15381624
)
15391625
}
15401626

15411627
pragma[nomagic]
15421628
private predicate flowOutOfCallAp(
1543-
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow,
1544-
Ap ap
1629+
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, Ap ap
15451630
) {
1546-
exists(ApApprox apa |
1547-
flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and
1631+
exists(ApApprox apa, boolean allowsFieldFlow |
1632+
flowOutOfCallApa(call, ret, _, _, out, allowsFieldFlow, apa) and
15481633
fwdFlow(ret, _, _, _, _, _, _, ap, apa) and
1549-
pos = ret.getReturnPosition()
1634+
pos = ret.getReturnPosition() and
1635+
if allowsFieldFlow = false then ap instanceof ApNil else any()
15501636
)
15511637
}
15521638

@@ -1627,10 +1713,9 @@ module MakeImpl<InputSig Lang> {
16271713
)
16281714
or
16291715
// flow into a callable
1630-
exists(ParamNodeEx p, boolean allowsFieldFlow |
1716+
exists(ParamNodeEx p |
16311717
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
1718+
flowIntoCallAp(_, node, p, ap) and
16341719
returnCtx = TReturnCtxNone()
16351720
)
16361721
or
@@ -1680,10 +1765,9 @@ module MakeImpl<InputSig Lang> {
16801765
DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state,
16811766
ReturnCtx returnCtx, ApOption returnAp, Ap ap
16821767
) {
1683-
exists(NodeEx out, boolean allowsFieldFlow |
1768+
exists(NodeEx out |
16841769
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()
1770+
flowOutOfCallAp(call, ret, pos, out, ap)
16871771
)
16881772
}
16891773

@@ -1872,11 +1956,23 @@ module MakeImpl<InputSig Lang> {
18721956
bindingset[node, cc]
18731957
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
18741958

1875-
bindingset[call, c, outercc]
1876-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
1959+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) { none() }
1960+
1961+
bindingset[call, ctx]
1962+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) { any() }
1963+
1964+
bindingset[call, c]
1965+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) { any() }
1966+
1967+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
1968+
none()
1969+
}
18771970

1878-
bindingset[call, c, innercc]
1879-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
1971+
bindingset[ctx]
1972+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) { any() }
1973+
1974+
bindingset[call, c]
1975+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) { any() }
18801976
}
18811977

18821978
private module Level1CallContext {
@@ -1899,9 +1995,17 @@ module MakeImpl<InputSig Lang> {
18991995
bindingset[node, cc]
19001996
LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
19011997

1902-
bindingset[call, c, outercc]
1903-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
1904-
checkCallContextCall(outercc, call, c) and
1998+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
1999+
result = prunedViableImplInCallContext(call, ctx)
2000+
}
2001+
2002+
bindingset[call, ctx]
2003+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
2004+
noPrunedViableImplInCallContext(call, ctx)
2005+
}
2006+
2007+
bindingset[call, c]
2008+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
19052009
if recordDataFlowCallSiteDispatch(call, c)
19062010
then result = TSpecificCall(call)
19072011
else result = TSomeCall()
@@ -1918,18 +2022,34 @@ module MakeImpl<InputSig Lang> {
19182022
node.getEnclosingCallable())
19192023
}
19202024

1921-
bindingset[call, c, outercc]
1922-
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
1923-
checkCallContextCall(outercc, call, c) and
2025+
DataFlowCallable viableImplCallContextReduced(DataFlowCall call, CcCall ctx) {
2026+
result = prunedViableImplInCallContext(call, ctx)
2027+
}
2028+
2029+
bindingset[call, ctx]
2030+
predicate viableImplNotCallContextReduced(DataFlowCall call, Cc ctx) {
2031+
noPrunedViableImplInCallContext(call, ctx)
2032+
}
2033+
2034+
bindingset[call, c]
2035+
CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c) {
19242036
if recordDataFlowCallSite(call, c)
19252037
then result = TSpecificCall(call)
19262038
else result = TSomeCall()
19272039
}
19282040
}
19292041

1930-
bindingset[call, c, innercc]
1931-
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
1932-
checkCallContextReturn(innercc, c, call) and
2042+
DataFlowCallable viableImplCallContextReducedReverse(DataFlowCall call, CcNoCall ctx) {
2043+
result = prunedViableImplInCallContextReverse(call, ctx)
2044+
}
2045+
2046+
bindingset[ctx]
2047+
predicate viableImplNotCallContextReducedReverse(CcNoCall ctx) {
2048+
ctx instanceof CallContextAny
2049+
}
2050+
2051+
bindingset[call, c]
2052+
CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call) {
19332053
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
19342054
}
19352055
}

0 commit comments

Comments
 (0)