mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Address review comments
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user