Skip to content

Commit 2ffbb2e

Browse files
committed
Java: Refactor dataflow to simplify return flow.
1 parent 1c79ec5 commit 2ffbb2e

File tree

3 files changed

+124
-123
lines changed

3 files changed

+124
-123
lines changed

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

Lines changed: 49 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi
258258
private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 }
259259

260260
pragma[noinline]
261-
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) {
262-
viableImpl(call) = result.getCallable() and
261+
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) {
262+
viableCallable(call) = result.getCallable() and
263263
kind = result.getKind()
264264
}
265265

@@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) {
313313
viableParamArg(_, node, arg)
314314
)
315315
or
316-
// flow out of an argument
317-
exists(PostUpdateNode mid, ParameterNode p |
318-
nodeCandFwd1(mid, config) and
319-
parameterValueFlowsToUpdate(p, mid) and
320-
viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode())
321-
)
322-
or
323316
// flow out of a callable
324-
exists(DataFlowCall call, ReturnNode ret, ReturnKind kind |
317+
exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind |
325318
nodeCandFwd1(ret, config) and
326319
getReturnPosition(ret) = viableReturnPos(call, kind) and
327-
node = getAnOutNode(call, kind)
320+
node = getAnOutNodeExt(call, kind)
328321
)
329322
)
330323
}
@@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) {
403396
nodeCand1(param, config)
404397
)
405398
or
406-
// flow out of an argument
407-
exists(PostUpdateNode mid, ParameterNode p |
408-
parameterValueFlowsToUpdate(p, node) and
409-
viableParamArg(_, p, mid.getPreUpdateNode()) and
410-
nodeCand1(mid, config)
411-
)
412-
or
413399
// flow out of a callable
414-
exists(DataFlowCall call, ReturnKind kind, OutNode out |
415-
nodeCand1(out, config) and
416-
getReturnPosition(node) = viableReturnPos(call, kind) and
417-
out = getAnOutNode(call, kind)
400+
exists(ReturnPosition pos |
401+
nodeCand1ReturnPosition(pos, config) and
402+
getReturnPosition(node) = pos
418403
)
419404
)
420405
}
421406

407+
pragma[noinline]
408+
private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) {
409+
exists(DataFlowCall call, ReturnKindExt kind, Node out |
410+
nodeCand1(out, config) and
411+
pos = viableReturnPos(call, kind) and
412+
out = getAnOutNodeExt(call, kind)
413+
)
414+
}
415+
422416
/**
423417
* Holds if `f` is the target of a read in the flow covered by `nodeCand1`.
424418
*/
@@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable(
565559
simpleArgumentFlowsThrough(node1, node2, _, config)
566560
}
567561

562+
pragma[noinline]
563+
private ReturnPosition getReturnPosition1(Node node, Configuration config) {
564+
result = getReturnPosition(node) and
565+
nodeCand1(node, config)
566+
}
567+
568568
/**
569569
* Holds if data can flow out of a callable from `node1` to `node2`, either
570570
* through a `ReturnNode` or through an argument that has been mutated, and
571571
* that this step is part of a path from a source to a sink.
572572
*/
573573
private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) {
574-
nodeCand1(node1, unbind(config)) and
575574
nodeCand1(node2, config) and
576575
not outBarrier(node1, config) and
577576
not inBarrier(node2, config) and
578-
(
579-
// flow out of an argument
580-
exists(ParameterNode p |
581-
parameterValueFlowsToUpdate(p, node1) and
582-
viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode())
583-
)
584-
or
585-
// flow out of a callable
586-
exists(DataFlowCall call, ReturnKind kind |
587-
getReturnPosition(node1) = viableReturnPos(call, kind) and
588-
node2 = getAnOutNode(call, kind)
589-
)
577+
exists(DataFlowCall call, ReturnKindExt kind |
578+
getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and
579+
node2 = getAnOutNodeExt(call, kind)
590580
)
591581
}
592582

@@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
17621752
or
17631753
exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap))
17641754
or
1765-
pathOutOfArgument(mid, node, cc) and ap = mid.getAp()
1766-
or
17671755
pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp()
17681756
or
17691757
pathOutOfCallable(mid, node, cc) and ap = mid.getAp()
@@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
17991787

18001788
pragma[noinline]
18011789
private predicate pathOutOfCallable1(
1802-
PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc
1790+
PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc
18031791
) {
18041792
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
18051793
pathOutOfCallable0(mid, pos, innercc) and
@@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1(
18161804
* is a return from a callable and is recorded by `cc`, if needed.
18171805
*/
18181806
pragma[noinline]
1819-
private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
1820-
exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) |
1821-
out = getAnOutNode(call, kind)
1822-
)
1823-
}
1824-
1825-
private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) {
1826-
exists(
1827-
PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i,
1828-
DataFlowCall call, ArgumentNode arg
1829-
|
1830-
mid.getNode() = n and
1831-
parameterValueFlowsToUpdate(p, n) and
1832-
innercc = mid.getCallContext() and
1833-
p.isParameterOf(callable, i) and
1834-
resolveReturn(innercc, callable, call) and
1835-
node.getPreUpdateNode() = arg and
1836-
arg.argumentOf(call, i) and
1837-
flow(node, unbind(mid.getConfiguration()))
1838-
|
1839-
if reducedViableImplInReturn(callable, call)
1840-
then cc = TReturn(callable, call)
1841-
else cc = TAnyCallContext()
1807+
private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
1808+
exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) |
1809+
out = getAnOutNodeExt(call, kind)
18421810
)
18431811
}
18441812

@@ -1900,9 +1868,9 @@ private predicate pathIntoCallable(
19001868
/** Holds if data may flow from `p` to a return of kind `kind`. */
19011869
pragma[nomagic]
19021870
private predicate paramFlowsThrough(
1903-
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
1871+
ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config
19041872
) {
1905-
exists(PathNodeMid mid, ReturnNode ret |
1873+
exists(PathNodeMid mid, ReturnNodeExt ret |
19061874
mid.getNode() = ret and
19071875
kind = ret.getKind() and
19081876
cc = mid.getCallContext() and
@@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough(
19191887

19201888
pragma[noinline]
19211889
private predicate pathThroughCallable0(
1922-
DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil
1890+
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil
19231891
) {
19241892
exists(ParameterNode p, CallContext innercc |
19251893
pathIntoCallable(mid, p, cc, innercc, call) and
19261894
paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and
1927-
not parameterValueFlowsThrough(p, kind, innercc) and
1895+
not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and
19281896
mid.getAp() instanceof AccessPathNil
19291897
)
19301898
}
@@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0(
19341902
* The context `cc` is restored to its value prior to entering the callable.
19351903
*/
19361904
pragma[noinline]
1937-
private predicate pathThroughCallable(
1938-
PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil
1939-
) {
1940-
exists(DataFlowCall call, ReturnKind kind |
1905+
private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) {
1906+
exists(DataFlowCall call, ReturnKindExt kind |
19411907
pathThroughCallable0(call, mid, kind, cc, apnil) and
1942-
out = getAnOutNode(call, kind)
1908+
out = getAnOutNodeExt(call, kind)
19431909
)
19441910
}
19451911

@@ -1996,16 +1962,10 @@ private module FlowExploration {
19961962
// flow into callable
19971963
viableParamArg(_, node2, node1)
19981964
or
1999-
// flow out of an argument
2000-
exists(ParameterNode p |
2001-
parameterValueFlowsToUpdate(p, node1) and
2002-
viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode())
2003-
)
2004-
or
20051965
// flow out of a callable
2006-
exists(DataFlowCall call, ReturnKind kind |
1966+
exists(DataFlowCall call, ReturnKindExt kind |
20071967
getReturnPosition(node1) = viableReturnPos(call, kind) and
2008-
node2 = getAnOutNode(call, kind)
1968+
node2 = getAnOutNodeExt(call, kind)
20091969
)
20101970
|
20111971
c1 = node1.getEnclosingCallable() and
@@ -2250,8 +2210,6 @@ private module FlowExploration {
22502210
apConsFwd(ap, f, ap0, config)
22512211
)
22522212
or
2253-
partialPathOutOfArgument(mid, node, cc, ap, config)
2254-
or
22552213
partialPathIntoCallable(mid, node, _, cc, _, ap, config)
22562214
or
22572215
partialPathOutOfCallable(mid, node, cc, ap, config)
@@ -2310,7 +2268,7 @@ private module FlowExploration {
23102268

23112269
pragma[noinline]
23122270
private predicate partialPathOutOfCallable1(
2313-
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
2271+
PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc,
23142272
PartialAccessPath ap, Configuration config
23152273
) {
23162274
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
@@ -2324,36 +2282,12 @@ private module FlowExploration {
23242282
}
23252283

23262284
private predicate partialPathOutOfCallable(
2327-
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
2285+
PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config
23282286
) {
2329-
exists(ReturnKind kind, DataFlowCall call |
2287+
exists(ReturnKindExt kind, DataFlowCall call |
23302288
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
23312289
|
2332-
out = getAnOutNode(call, kind)
2333-
)
2334-
}
2335-
2336-
private predicate partialPathOutOfArgument(
2337-
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
2338-
Configuration config
2339-
) {
2340-
exists(
2341-
PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i,
2342-
DataFlowCall call, ArgumentNode arg
2343-
|
2344-
mid.getNode() = n and
2345-
parameterValueFlowsToUpdate(p, n) and
2346-
innercc = mid.getCallContext() and
2347-
p.isParameterOf(callable, i) and
2348-
resolveReturn(innercc, callable, call) and
2349-
node.getPreUpdateNode() = arg and
2350-
arg.argumentOf(call, i) and
2351-
ap = mid.getAp() and
2352-
config = mid.getConfiguration()
2353-
|
2354-
if reducedViableImplInReturn(callable, call)
2355-
then cc = TReturn(callable, call)
2356-
else cc = TAnyCallContext()
2290+
out = getAnOutNodeExt(call, kind)
23572291
)
23582292
}
23592293

@@ -2400,10 +2334,10 @@ private module FlowExploration {
24002334

24012335
pragma[nomagic]
24022336
private predicate paramFlowsThroughInPartialPath(
2403-
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
2337+
ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil,
24042338
Configuration config
24052339
) {
2406-
exists(PartialPathNodePriv mid, ReturnNode ret |
2340+
exists(PartialPathNodePriv mid, ReturnNodeExt ret |
24072341
mid.getNode() = ret and
24082342
kind = ret.getKind() and
24092343
cc = mid.getCallContext() and
@@ -2420,23 +2354,23 @@ private module FlowExploration {
24202354

24212355
pragma[noinline]
24222356
private predicate partialPathThroughCallable0(
2423-
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
2357+
DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc,
24242358
PartialAccessPathNil apnil, Configuration config
24252359
) {
24262360
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
24272361
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
24282362
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
2429-
not parameterValueFlowsThrough(p, kind, innercc)
2363+
not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc)
24302364
)
24312365
}
24322366

24332367
private predicate partialPathThroughCallable(
2434-
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
2368+
PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil,
24352369
Configuration config
24362370
) {
2437-
exists(DataFlowCall call, ReturnKind kind |
2371+
exists(DataFlowCall call, ReturnKindExt kind |
24382372
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
2439-
out = getAnOutNode(call, kind)
2373+
out = getAnOutNodeExt(call, kind)
24402374
)
24412375
}
24422376

0 commit comments

Comments
 (0)