Address review comments

This commit is contained in:
Tom Hvitved
2019-04-29 20:07:39 +02:00
parent 813dfc6417
commit 29e59e6d1e
21 changed files with 357 additions and 292 deletions

View File

@@ -202,16 +202,10 @@ private module DispatchImpl {
reducedViableImplInReturn(result, ma)
}
/**
* Gets a node that can read the value returned at position `pos` for the
* call `call`.
*/
/** Gets a node that can read the value returned at position `pos`. */
cached
OutNode getAnOutputAtCall(DataFlowCall call, ReturnPosition pos) {
exists(Method m | pos.getCallable() = m |
m = viableCallable(call) and
result = call.getNode()
)
OutNode getAViableOutNode(ReturnPosition pos) {
pos.getCallable() = viableCallable(result.getCall())
}
}
import DispatchImpl

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -23,6 +23,29 @@ private module ImplCommon {
)
}
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of a call
* that can return values at position `pos` out to the node `out`. The instance
* parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParamOut(int i, ParameterNode p, OutNode out, ReturnPosition ret) {
out = getAViableOutNode(ret) and
p.isParameterOf(ret.getCallable(), i)
}
/**
* Holds if `arg` is a possible argument to `p` taking virtual dispatch into account,
* and the callable can return values at position `pos` out to the node `out`.
*/
cached
predicate viableParamArgOut(ParameterNode p, ArgumentNode arg, ReturnPosition ret, OutNode out) {
exists(int i |
viableParamOut(i, p, out, ret) and
arg.argumentOf(out.getCall(), i)
)
}
/**
* Holds if `p` can flow to `node` in the same callable using only
* value-preserving steps.
@@ -54,14 +77,13 @@ private module ImplCommon {
}
/**
* Holds if `arg` flows through `call` using only value-preserving steps.
* Holds if `arg` flows through a call to `out` using only value-preserving steps.
*/
cached
predicate argumentValueFlowsThrough(ArgumentNode arg, Node out) {
predicate argumentValueFlowsThrough(ArgumentNode arg, OutNode out) {
exists(ParameterNode param, ReturnPosition ret |
viableParamArg(param, arg) and
viableParamArgOut(param, arg, ret, out) and
parameterValueFlowsThrough(param, ret) and
out = getAnOutputAtCall(arg.getCall(), ret) and
compatibleTypes(arg.getType(), out.getType())
)
}
@@ -139,21 +161,20 @@ private module ImplCommon {
}
private predicate storeReturn(Node node1, Content f, Node node2) {
exists(ParameterNode p, ArgumentNode arg |
exists(ParameterNode p, ArgumentNode arg, ReturnPosition ret |
arg = node1 and
viableParamArg(p, arg) and
setterReturn(p, f) and
node2 = arg.getCall().getNode() and
viableParamArgOut(p, arg, ret, node2) and
setterReturn(p, f, ret) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
)
}
private predicate setterReturn(ParameterNode p, Content f) {
exists(Node n1, Node n2, ReturnNode ret |
private predicate setterReturn(ParameterNode p, Content f, ReturnPosition ret) {
exists(Node n1, Node n2 |
parameterValueFlow(p, n1) and
store(n1, f, n2) and
localValueStep*(n2, ret)
localValueStep*(n2, ret.getAReturnNode())
)
}
@@ -165,21 +186,20 @@ private module ImplCommon {
predicate read(Node node1, Content f, Node node2) {
readStep(node1, f, node2) and storeStep(_, f, _)
or
exists(ParameterNode p, ArgumentNode arg |
exists(ParameterNode p, ArgumentNode arg, ReturnPosition ret |
arg = node1 and
viableParamArg(p, arg) and
getter(p, f) and
node2 = arg.getCall().getNode() and
viableParamArgOut(p, arg, ret, node2) and
getter(p, f, ret) and
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
compatibleTypes(node2.getTypeBound(), f.getType())
)
}
private predicate getter(ParameterNode p, Content f) {
exists(Node n1, Node n2, ReturnNode ret |
private predicate getter(ParameterNode p, Content f, ReturnPosition ret) {
exists(Node n1, Node n2 |
parameterValueFlow(p, n1) and
read(n1, f, n2) and
localValueStep*(n2, ret)
localValueStep*(n2, ret.getAReturnNode())
)
}

View File

@@ -206,7 +206,7 @@ private predicate nodeCandFwd1(Node node, boolean stored, Configuration config)
// flow out of a callable
exists(ReturnNode ret |
nodeCandFwd1(ret, stored, config) and
node = getAnOutputAtCall(_, ret.getPosition())
node = getAViableOutNode(ret.getPosition())
)
)
}
@@ -282,7 +282,7 @@ private predicate nodeCand1(Node node, boolean stored, Configuration config) {
// flow out of a callable
exists(Node out |
nodeCand1(out, stored, config) and
out = getAnOutputAtCall(_, node.(ReturnNode).getPosition())
out = getAViableOutNode(node.(ReturnNode).getPosition())
)
)
}
@@ -366,9 +366,8 @@ private predicate simpleArgumentFlowsThrough(
exists(ParameterNode param, ReturnNode ret |
nodeCand1(arg, false, unbind(config)) and
nodeCand1(out, false, unbind(config)) and
viableParamArg(param, arg) and
simpleParameterFlow(param, ret, t, config) and
out = getAnOutputAtCall(arg.getCall(), ret.getPosition())
viableParamArgOut(param, arg, ret.getPosition(), out) and
simpleParameterFlow(param, ret, t, config)
)
}
@@ -410,7 +409,7 @@ private predicate flowOutOfCallableCand1(Node node1, Node node2, Configuration c
)
or
// flow out of a callable
node2 = getAnOutputAtCall(_, node1.(ReturnNode).getPosition())
node2 = getAViableOutNode(node1.(ReturnNode).getPosition())
)
}
@@ -1439,7 +1438,7 @@ private predicate flowStep(PathNodeMid mid, Node node, CallContext cc, AccessPat
or
flowOutOfCallable(mid, node, cc) and ap = mid.getAp()
or
flowThroughCallable(mid, node, cc) and ap = mid.getAp()
flowThroughCallable(mid, node, ap, cc)
}
private predicate contentReadStep(PathNodeMid mid, Node node, AccessPath ap) {
@@ -1474,11 +1473,12 @@ private predicate flowOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
private predicate flowOutOfCallable(PathNodeMid mid, Node out, CallContext cc) {
private predicate flowOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) {
exists(ReturnPosition pos, DataFlowCallable c, DataFlowCall call, CallContext innercc |
flowOutOfCallable0(mid, pos, innercc) and
out = getAnOutputAtCall(call, pos) and
out = getAViableOutNode(pos) and
c = pos.getCallable() and
call = out.getCall() and
resolveReturn(innercc, c, call)
|
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
@@ -1563,11 +1563,12 @@ private predicate flowIntoCallable(
/** Holds if data may flow from `p` to a return at position `pos`. */
pragma[nomagic]
private predicate paramFlowsThrough(
ParameterNode p, ReturnPosition pos, CallContextCall cc, Configuration config
ParameterNode p, ReturnPosition pos, AccessPath ap, CallContextCall cc, Configuration config
) {
exists(PathNodeMid mid |
mid.getNode() = pos.getAReturnNode() and
cc = mid.getCallContext() and
ap = mid.getAp() and
config = mid.getConfiguration()
|
cc = TSomeCall(p, true)
@@ -1581,11 +1582,11 @@ private predicate paramFlowsThrough(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
private predicate flowThroughCallable(PathNodeMid mid, Node out, CallContext cc) {
exists(DataFlowCall call, ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, call) and
paramFlowsThrough(p, pos, innercc, unbind(mid.getConfiguration())) and
out = getAnOutputAtCall(call, pos)
private predicate flowThroughCallable(PathNodeMid mid, OutNode out, AccessPath ap, CallContext cc) {
exists(ParameterNode p, ReturnPosition pos, CallContext innercc |
flowIntoCallable(mid, p, cc, innercc, out.getCall()) and
paramFlowsThrough(p, pos, ap, innercc, unbind(mid.getConfiguration())) and
out = getAViableOutNode(pos)
)
}

View File

@@ -46,7 +46,10 @@ class ReturnNode extends ExprNode {
/** A data flow node that represents a call. */
class OutNode extends ExprNode {
OutNode() { this.getExpr() instanceof Call }
OutNode() { this.getExpr() instanceof MethodAccess }
/** Gets the underlying call. */
DataFlowCall getCall() { result = this.getExpr() }
}
/**