Skip to content

Commit 6d022aa

Browse files
committed
Java/C++/C#: Sync dataflow.
1 parent 7c30c1a commit 6d022aa

File tree

13 files changed

+1053
-364
lines changed

13 files changed

+1053
-364
lines changed

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

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ abstract class Configuration extends string {
5757
/** Holds if data flow through `node` is prohibited. */
5858
predicate isBarrier(Node node) { none() }
5959

60-
/** Holds if data flow from `node1` to `node2` is prohibited. */
61-
predicate isBarrierEdge(Node node1, Node node2) { none() }
60+
/** DEPRECATED: override `isBarrier` instead. */
61+
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
6262

6363
/**
6464
* Holds if the additional flow step from `node1` to `node2` must be taken
@@ -103,6 +103,22 @@ abstract class Configuration extends string {
103103
deprecated predicate hasFlowBackward(Node source, Node sink) { hasFlow(source, sink) }
104104
}
105105

106+
private predicate inBarrier(Node node, Configuration config) {
107+
config.isBarrier(node) and
108+
config.isSource(node)
109+
}
110+
111+
private predicate outBarrier(Node node, Configuration config) {
112+
config.isBarrier(node) and
113+
config.isSink(node)
114+
}
115+
116+
private predicate fullBarrier(Node node, Configuration config) {
117+
config.isBarrier(node) and
118+
not config.isSource(node) and
119+
not config.isSink(node)
120+
}
121+
106122
private class AdditionalFlowStepSource extends Node {
107123
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
108124
}
@@ -119,22 +135,46 @@ private predicate isAdditionalFlowStep(
119135
* Holds if data can flow in one local step from `node1` to `node2`.
120136
*/
121137
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
122-
localFlowStep(node1, node2) and not config.isBarrierEdge(node1, node2)
138+
localFlowStep(node1, node2) and
139+
not outBarrier(node1, config) and
140+
not inBarrier(node2, config) and
141+
not fullBarrier(node1, config) and
142+
not fullBarrier(node2, config)
123143
}
124144

125145
/**
126146
* Holds if the additional step from `node1` to `node2` does not jump between callables.
127147
*/
128148
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
129-
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config)
149+
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
150+
not outBarrier(node1, config) and
151+
not inBarrier(node2, config) and
152+
not fullBarrier(node1, config) and
153+
not fullBarrier(node2, config)
154+
}
155+
156+
/**
157+
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
158+
*/
159+
private predicate jumpStep(Node node1, Node node2, Configuration config) {
160+
jumpStep(node1, node2) and
161+
not outBarrier(node1, config) and
162+
not inBarrier(node2, config) and
163+
not fullBarrier(node1, config) and
164+
not fullBarrier(node2, config)
130165
}
131166

132167
/**
133168
* Holds if the additional step from `node1` to `node2` jumps between callables.
134169
*/
135170
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
136-
exists(DataFlowCallable callable1 | isAdditionalFlowStep(node1, node2, callable1, config) |
137-
node2.getEnclosingCallable() != callable1
171+
exists(DataFlowCallable callable1 |
172+
isAdditionalFlowStep(node1, node2, callable1, config) and
173+
node2.getEnclosingCallable() != callable1 and
174+
not outBarrier(node1, config) and
175+
not inBarrier(node2, config) and
176+
not fullBarrier(node1, config) and
177+
not fullBarrier(node2, config)
138178
)
139179
}
140180

@@ -154,7 +194,7 @@ private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) {
154194
* ignoring call contexts.
155195
*/
156196
private predicate nodeCandFwd1(Node node, boolean stored, Configuration config) {
157-
not config.isBarrier(node) and
197+
not fullBarrier(node, config) and
158198
(
159199
config.isSource(node) and stored = false
160200
or
@@ -171,7 +211,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
171211
or
172212
exists(Node mid |
173213
nodeCandFwd1(mid, stored, config) and
174-
jumpStep(mid, node)
214+
jumpStep(mid, node, config)
175215
)
176216
or
177217
exists(Node mid |
@@ -185,15 +225,17 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
185225
useFieldFlow(config) and
186226
nodeCandFwd1(mid, _, config) and
187227
store(mid, _, node) and
188-
stored = true
228+
stored = true and
229+
not outBarrier(mid, config)
189230
)
190231
or
191232
// read
192233
exists(Node mid, Content f |
193234
nodeCandFwd1(mid, true, config) and
194235
read(mid, f, node) and
195236
storeCandFwd1(f, unbind(config)) and
196-
(stored = false or stored = true)
237+
(stored = false or stored = true) and
238+
not inBarrier(node, config)
197239
)
198240
or
199241
// flow into a callable
@@ -223,7 +265,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
223265
*/
224266
private predicate storeCandFwd1(Content f, Configuration config) {
225267
exists(Node mid, Node node |
226-
not config.isBarrier(node) and
268+
not fullBarrier(node, config) and
227269
useFieldFlow(config) and
228270
nodeCandFwd1(mid, _, config) and
229271
store(mid, f, node)
@@ -257,7 +299,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
257299
)
258300
or
259301
exists(Node mid |
260-
jumpStep(node, mid) and
302+
jumpStep(node, mid, config) and
261303
nodeCand1(mid, stored, config)
262304
)
263305
or
@@ -318,6 +360,11 @@ private predicate readCand1(Content f, Configuration config) {
318360
)
319361
}
320362

363+
private predicate throughFlowNodeCand(Node node, Configuration config) {
364+
nodeCand1(node, false, config) and
365+
not config.isBarrier(node)
366+
}
367+
321368
/**
322369
* Holds if there is a path from `p` to `node` in the same callable that is
323370
* part of a path from a source to a sink taking simple call contexts into
@@ -329,7 +376,7 @@ pragma[nomagic]
329376
private predicate simpleParameterFlow(
330377
ParameterNode p, Node node, DataFlowType t, Configuration config
331378
) {
332-
nodeCand1(node, false, config) and
379+
throughFlowNodeCand(node, config) and
333380
p = node and
334381
t = getErasedRepr(node.getType()) and
335382
exists(ReturnNode ret, ReturnKind kind |
@@ -338,37 +385,37 @@ private predicate simpleParameterFlow(
338385
not parameterValueFlowsThrough(p, kind, _)
339386
)
340387
or
341-
nodeCand1(node, false, unbind(config)) and
388+
throughFlowNodeCand(node, unbind(config)) and
342389
exists(Node mid |
343390
simpleParameterFlow(p, mid, t, config) and
344391
localFlowStep(mid, node, config) and
345392
compatibleTypes(t, node.getType())
346393
)
347394
or
348-
nodeCand1(node, false, unbind(config)) and
395+
throughFlowNodeCand(node, unbind(config)) and
349396
exists(Node mid |
350397
simpleParameterFlow(p, mid, _, config) and
351398
additionalLocalFlowStep(mid, node, config) and
352399
t = getErasedRepr(node.getType())
353400
)
354401
or
355-
nodeCand1(node, false, unbind(config)) and
402+
throughFlowNodeCand(node, unbind(config)) and
356403
exists(Node mid |
357404
simpleParameterFlow(p, mid, t, config) and
358405
localStoreReadStep(mid, node) and
359406
compatibleTypes(t, node.getType())
360407
)
361408
or
362409
// value flow through a callable
363-
nodeCand1(node, false, unbind(config)) and
410+
throughFlowNodeCand(node, unbind(config)) and
364411
exists(Node arg |
365412
simpleParameterFlow(p, arg, t, config) and
366413
argumentValueFlowsThrough(arg, node, _) and
367414
compatibleTypes(t, node.getType())
368415
)
369416
or
370417
// flow through a callable
371-
nodeCand1(node, false, unbind(config)) and
418+
throughFlowNodeCand(node, unbind(config)) and
372419
exists(Node arg |
373420
simpleParameterFlow(p, arg, _, config) and
374421
simpleArgumentFlowsThrough(arg, node, t, config)
@@ -380,6 +427,7 @@ private predicate simpleArgumentFlowsThrough0(
380427
DataFlowCall call, ArgumentNode arg, ReturnKind kind, DataFlowType t, Configuration config
381428
) {
382429
nodeCand1(arg, false, unbind(config)) and
430+
not outBarrier(arg, config) and
383431
exists(ParameterNode p, ReturnNode ret |
384432
simpleParameterFlow(p, ret, t, config) and
385433
kind = ret.getKind() and
@@ -399,6 +447,7 @@ private predicate simpleArgumentFlowsThrough(
399447
) {
400448
exists(DataFlowCall call, ReturnKind kind |
401449
nodeCand1(out, false, unbind(config)) and
450+
not inBarrier(out, config) and
402451
simpleArgumentFlowsThrough0(call, arg, kind, t, config) and
403452
out = getAnOutNode(call, kind)
404453
)
@@ -440,6 +489,8 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable(
440489
private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) {
441490
nodeCand1(node1, _, unbind(config)) and
442491
nodeCand1(node2, _, config) and
492+
not outBarrier(node1, config) and
493+
not inBarrier(node2, config) and
443494
(
444495
// flow out of an argument
445496
exists(ParameterNode p |
@@ -462,7 +513,9 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config
462513
private predicate flowIntoCallable(Node node1, Node node2, Configuration config) {
463514
viableParamArg(_, node2, node1) and
464515
nodeCand1(node1, _, unbind(config)) and
465-
nodeCand1(node2, _, config)
516+
nodeCand1(node2, _, config) and
517+
not outBarrier(node1, config) and
518+
not inBarrier(node2, config)
466519
}
467520

468521
/**
@@ -546,7 +599,7 @@ private predicate nodeCandFwd2(Node node, boolean fromArg, boolean stored, Confi
546599
or
547600
exists(Node mid |
548601
nodeCandFwd2(mid, _, stored, config) and
549-
jumpStep(mid, node) and
602+
jumpStep(mid, node, config) and
550603
fromArg = false
551604
)
552605
or
@@ -626,7 +679,7 @@ private predicate nodeCand2(Node node, boolean toReturn, boolean stored, Configu
626679
)
627680
or
628681
exists(Node mid |
629-
jumpStep(node, mid) and
682+
jumpStep(node, mid, config) and
630683
nodeCand2(mid, _, stored, config) and
631684
toReturn = false
632685
)
@@ -714,7 +767,7 @@ private predicate localFlowEntry(Node node, Configuration config) {
714767
nodeCand(node, config) and
715768
(
716769
config.isSource(node) or
717-
jumpStep(_, node) or
770+
jumpStep(_, node, config) or
718771
additionalJumpStep(_, node, config) or
719772
node instanceof ParameterNode or
720773
node instanceof OutNode or
@@ -730,7 +783,7 @@ private predicate localFlowEntry(Node node, Configuration config) {
730783
*/
731784
private predicate localFlowExit(Node node, Configuration config) {
732785
exists(Node next | nodeCand(next, config) |
733-
jumpStep(node, next) or
786+
jumpStep(node, next, config) or
734787
additionalJumpStep(node, next, config) or
735788
flowIntoCallable(node, next, config) or
736789
flowOutOfCallable(node, next, config) or
@@ -882,7 +935,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
882935
or
883936
exists(Node mid |
884937
flowCandFwd(mid, _, apf, config) and
885-
jumpStep(mid, node) and
938+
jumpStep(mid, node, config) and
886939
fromArg = false
887940
)
888941
or
@@ -973,7 +1026,7 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
9731026
)
9741027
or
9751028
exists(Node mid |
976-
jumpStep(node, mid) and
1029+
jumpStep(node, mid, config) and
9771030
flowCand(mid, _, apf, config) and
9781031
toReturn = false
9791032
)
@@ -1154,7 +1207,7 @@ private predicate flowFwd0(
11541207
or
11551208
exists(Node mid |
11561209
flowFwd(mid, _, apf, ap, config) and
1157-
jumpStep(mid, node) and
1210+
jumpStep(mid, node, config) and
11581211
fromArg = false
11591212
)
11601213
or
@@ -1263,7 +1316,7 @@ private predicate flow0(Node node, boolean toReturn, AccessPath ap, Configuratio
12631316
)
12641317
or
12651318
exists(Node mid |
1266-
jumpStep(node, mid) and
1319+
jumpStep(node, mid, config) and
12671320
flow(mid, _, ap, config) and
12681321
toReturn = false
12691322
)
@@ -1518,7 +1571,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
15181571
mid.getAp() instanceof AccessPathNil and
15191572
ap = node.(AccessPathNilNode).getAp()
15201573
or
1521-
jumpStep(mid.getNode(), node) and
1574+
jumpStep(mid.getNode(), node, mid.getConfiguration()) and
15221575
cc instanceof CallContextAny and
15231576
ap = mid.getAp()
15241577
or

0 commit comments

Comments
 (0)