Skip to content

Commit e8cea79

Browse files
committed
Dataflow: Sync.
1 parent ad461a8 commit e8cea79

File tree

7 files changed

+588
-280
lines changed

7 files changed

+588
-280
lines changed

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 84 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
11351135
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
11361136
);
11371137

1138-
bindingset[node, state, t, ap]
1139-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
1138+
bindingset[node, state, t0, ap]
1139+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
11401140

11411141
bindingset[typ, contentType]
11421142
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,17 +1199,20 @@ module Impl<FullStateConfigSig Config> {
11991199
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
12001200
ApOption argAp, Typ t, Ap ap, ApApprox apa
12011201
) {
1202-
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
1203-
PrevStage::revFlow(node, state, apa) and
1204-
filter(node, state, t, ap)
1202+
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
12051203
}
12061204

1207-
pragma[inline]
1208-
additional predicate fwdFlow(
1205+
private predicate fwdFlow1(
12091206
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
1210-
ApOption argAp, Typ t, Ap ap
1207+
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
12111208
) {
1212-
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
1209+
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
1210+
PrevStage::revFlow(node, state, apa) and
1211+
filter(node, state, t0, ap, t)
1212+
}
1213+
1214+
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
1215+
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
12131216
}
12141217

12151218
pragma[assume_small_delta]
@@ -1339,6 +1342,11 @@ module Impl<FullStateConfigSig Config> {
13391342
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
13401343
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
13411344
cons = apCons(c, t1, tail)
1345+
or
1346+
exists(Typ t0 |
1347+
typeStrengthen(t0, cons, t2) and
1348+
fwdFlowConsCand(t0, cons, c, t1, tail)
1349+
)
13421350
}
13431351

13441352
pragma[nomagic]
@@ -1359,7 +1367,7 @@ module Impl<FullStateConfigSig Config> {
13591367
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
13601368
) {
13611369
exists(ApHeadContent apc |
1362-
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
1370+
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
13631371
apc = getHeadContent(ap) and
13641372
readStepCand0(node1, apc, c, node2)
13651373
)
@@ -1520,14 +1528,14 @@ module Impl<FullStateConfigSig Config> {
15201528
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
15211529
) {
15221530
revFlow0(node, state, returnCtx, returnAp, ap) and
1523-
fwdFlow(node, state, _, _, _, _, _, ap)
1531+
fwdFlow(node, state, _, _, _, _, _, ap, _)
15241532
}
15251533

15261534
pragma[nomagic]
15271535
private predicate revFlow0(
15281536
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
15291537
) {
1530-
fwdFlow(node, state, _, _, _, _, _, ap) and
1538+
fwdFlow(node, state, _, _, _, _, _, ap, _) and
15311539
sinkNode(node, state) and
15321540
(
15331541
if hasSinkCallCtx()
@@ -1780,13 +1788,13 @@ module Impl<FullStateConfigSig Config> {
17801788
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
17811789
) {
17821790
fwd = true and
1783-
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
1791+
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
17841792
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
17851793
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
1786-
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
1794+
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
17871795
tuples =
17881796
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
1789-
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
1797+
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
17901798
or
17911799
fwd = false and
17921800
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1963,10 +1971,10 @@ module Impl<FullStateConfigSig Config> {
19631971
)
19641972
}
19651973

1966-
bindingset[node, state, t, ap]
1967-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
1974+
bindingset[node, state, t0, ap]
1975+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
19681976
PrevStage::revFlowState(state) and
1969-
exists(t) and
1977+
t0 = t and
19701978
exists(ap) and
19711979
not stateBarrier(node, state) and
19721980
(
@@ -2197,8 +2205,8 @@ module Impl<FullStateConfigSig Config> {
21972205
import BooleanCallContext
21982206

21992207
predicate localStep(
2200-
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
2201-
DataFlowType t, LocalCc lcc
2208+
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
2209+
LocalCc lcc
22022210
) {
22032211
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
22042212
exists(lcc)
@@ -2218,10 +2226,16 @@ module Impl<FullStateConfigSig Config> {
22182226
)
22192227
}
22202228

2221-
bindingset[node, state, t, ap]
2222-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2229+
bindingset[node, state, t0, ap]
2230+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
22232231
exists(state) and
2224-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2232+
// We can get away with not using type strengthening here, since we aren't
2233+
// going to use the tracked types in the construction of Stage 4 access
2234+
// paths. For Stage 4 and onwards, the tracked types must be consistent as
2235+
// the cons candidates including types are used to construct subsequent
2236+
// access path approximations.
2237+
t0 = t and
2238+
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
22252239
(
22262240
notExpectsContent(node)
22272241
or
@@ -2274,8 +2288,8 @@ module Impl<FullStateConfigSig Config> {
22742288

22752289
pragma[nomagic]
22762290
predicate localStep(
2277-
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
2278-
DataFlowType t, LocalCc lcc
2291+
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
2292+
LocalCc lcc
22792293
) {
22802294
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
22812295
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2333,11 +2347,18 @@ module Impl<FullStateConfigSig Config> {
23332347
)
23342348
}
23352349

2336-
bindingset[node, state, t, ap]
2337-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2350+
bindingset[node, state, t0, ap]
2351+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
23382352
exists(state) and
23392353
not clear(node, ap) and
2340-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2354+
(
2355+
if castingNodeEx(node)
2356+
then
2357+
exists(Typ nt | nt = node.getDataFlowType() |
2358+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
2359+
)
2360+
else t = t0
2361+
) and
23412362
(
23422363
notExpectsContent(node)
23432364
or
@@ -2365,7 +2386,7 @@ module Impl<FullStateConfigSig Config> {
23652386
exists(AccessPathFront apf |
23662387
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
23672388
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
2368-
apf)
2389+
apf, _)
23692390
)
23702391
}
23712392

@@ -2579,8 +2600,8 @@ module Impl<FullStateConfigSig Config> {
25792600
import LocalCallContext
25802601

25812602
predicate localStep(
2582-
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
2583-
DataFlowType t, LocalCc lcc
2603+
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
2604+
LocalCc lcc
25842605
) {
25852606
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
25862607
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2609,9 +2630,16 @@ module Impl<FullStateConfigSig Config> {
26092630
)
26102631
}
26112632

2612-
bindingset[node, state, t, ap]
2613-
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
2614-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
2633+
bindingset[node, state, t0, ap]
2634+
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
2635+
(
2636+
if castingNodeEx(node)
2637+
then
2638+
exists(Typ nt | nt = node.getDataFlowType() |
2639+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
2640+
)
2641+
else t = t0
2642+
) and
26152643
exists(state) and
26162644
exists(ap)
26172645
}
@@ -2632,7 +2660,7 @@ module Impl<FullStateConfigSig Config> {
26322660
Stage5::parameterMayFlowThrough(p, _) and
26332661
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
26342662
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
2635-
TAccessPathApproxSome(apa), _, apa0)
2663+
TAccessPathApproxSome(apa), _, apa0, _)
26362664
)
26372665
}
26382666

@@ -2649,7 +2677,7 @@ module Impl<FullStateConfigSig Config> {
26492677
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
26502678
exists(AccessPathApprox apa | ap.getApprox() = apa |
26512679
Stage5::parameterMayFlowThrough(p, apa) and
2652-
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
2680+
Stage5::fwdFlow(p, state, _, _, _, _, t, apa, _) and
26532681
Stage5::revFlow(p, state, _)
26542682
)
26552683
}
@@ -2820,9 +2848,7 @@ module Impl<FullStateConfigSig Config> {
28202848
ap = TAccessPathNil()
28212849
or
28222850
// ... or a step from an existing PathNode to another node.
2823-
pathStep(_, node, state, cc, sc, t, ap) and
2824-
Stage5::revFlow(node, state, ap.getApprox()) and
2825-
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
2851+
pathStep(_, node, state, cc, sc, t, ap)
28262852
} or
28272853
TPathNodeSink(NodeEx node, FlowState state) {
28282854
exists(PathNodeMid sink |
@@ -3340,13 +3366,31 @@ module Impl<FullStateConfigSig Config> {
33403366
ap = mid.getAp()
33413367
}
33423368

3369+
private predicate pathStep(
3370+
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
3371+
AccessPath ap
3372+
) {
3373+
exists(DataFlowType t0 |
3374+
pathStep0(mid, node, state, cc, sc, t0, ap) and
3375+
Stage5::revFlow(node, state, ap.getApprox()) and
3376+
(
3377+
if castingNodeEx(node)
3378+
then
3379+
exists(DataFlowType nt | nt = node.getDataFlowType() |
3380+
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
3381+
)
3382+
else t = t0
3383+
)
3384+
)
3385+
}
3386+
33433387
/**
33443388
* Holds if data may flow from `mid` to `node`. The last step in or out of
33453389
* a callable is recorded by `cc`.
33463390
*/
33473391
pragma[assume_small_delta]
33483392
pragma[nomagic]
3349-
private predicate pathStep(
3393+
private predicate pathStep0(
33503394
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
33513395
AccessPath ap
33523396
) {

0 commit comments

Comments
 (0)