Merge pull request #7260 from hvitved/dataflow/argument-parameter-matching

Data flow: Introduce `ParameterPosition` and `ArgumentPosition`
This commit is contained in:
Anders Schack-Mulligen
2021-12-08 12:49:08 +01:00
committed by GitHub
56 changed files with 2167 additions and 1605 deletions

View File

@@ -1,4 +1,6 @@
private import cpp
private import semmle.code.cpp.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.dataflow.internal.DataFlowUtil
/**
* Gets a function that might be called by `call`.
@@ -63,3 +65,17 @@ predicate mayBenefitFromCallContext(Call call, Function f) { none() }
* restricted to those `call`s for which a context might make a difference.
*/
Function viableImplInCallContext(Call call, Call ctx) { none() }
/** A parameter position represented by an integer. */
class ParameterPosition extends int {
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
}
/** An argument position represented by an integer. */
class ArgumentPosition extends int {
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
}
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
tupleLimit = 1000
}
/**
* Holds if `arg` is an argument of `call` with an argument position that matches
* parameter position `ppos`.
*/
pragma[noinline]
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
exists(ArgumentPosition apos |
arg.argumentOf(call, apos) and
parameterMatch(ppos, apos)
)
}
/**
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
* currently excludes read-steps, store-steps, and flow-through.
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
pragma[noinline]
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallable(call), ppos)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
pragma[noinline]
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), ppos)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamNonLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
@@ -322,7 +336,7 @@ private module Cached {
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
)
}
@@ -330,7 +344,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
exists(ParamNode p, ParameterPosition pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -352,11 +366,13 @@ private module Cached {
}
cached
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
isParameterNode(p, c, pos)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
isArgumentNode(n, call, pos)
}
/**
@@ -374,12 +390,12 @@ private module Cached {
}
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
* The instance parameter is considered to have index `-1`.
* Holds if `p` is the parameter of a viable dispatch target of `call`,
* and `p` has position `ppos`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableExt(call), ppos)
}
/**
@@ -388,9 +404,9 @@ private module Cached {
*/
cached
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
exists(ParameterPosition ppos |
viableParam(call, ppos, p) and
argumentPositionMatch(call, arg, ppos) and
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -862,7 +878,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
* position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
}
/** A data-flow node that represents a call argument. */
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
argumentNode(this, call, pos)
}
}
/**
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
private int pos;
private ParameterPosition pos;
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
int getPosition() { result = pos }
ParameterPosition getPosition() { result = pos }
pragma[nomagic]
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
override string toString() { result = "param update " + pos }
}

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c, pos)
}
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
arg.argumentOf(c, pos)
}
/** Gets the instance argument of a non-static call. */
private Node getInstanceArgument(Call call) {

View File

@@ -2,6 +2,7 @@ private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
/**
@@ -266,3 +267,17 @@ Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget()
)
}
/** A parameter position represented by an integer. */
class ParameterPosition extends int {
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
}
/** An argument position represented by an integer. */
class ArgumentPosition extends int {
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
}
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
predicate isParameterOf(DataFlowCallable c, int i) {
this.asNode().(ParamNode).isParameterOf(c, i)
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
this.asNode().(ParamNode).isParameterOf(c, pos)
}
int getPosition() { this.isParameterOf(_, result) }
ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -1447,7 +1447,7 @@ private module Stage2 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2142,7 +2142,7 @@ private module Stage3 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2908,7 +2908,7 @@ private module Stage4 {
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
@@ -2992,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
int getParameterPos() { p.isParameterOf(_, result) }
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3639,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
Configuration config
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
AccessPathApprox apa, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
apa = ap.getApprox() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
AccessPath ap, Configuration config
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3686,9 +3687,9 @@ private predicate pathIntoCallable(
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call, Configuration config
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
(
sc = TSummaryCtxSome(p, ap)
or
@@ -3712,7 +3713,7 @@ private predicate paramFlowsThrough(
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
Configuration config
) {
exists(PathNodeMid mid, RetNodeEx ret, int pos |
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
mid.getNodeEx() = ret and
kind = ret.getKind() and
cc = mid.getCallContext() and
@@ -4441,24 +4442,25 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
PartialAccessPath ap, Configuration config
) {
exists(ArgNode arg |
exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
arg.argumentOf(call, apos) and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
DataFlowCall call, PartialAccessPath ap, Configuration config
) {
partialPathIntoArg(mid, i, outercc, call, ap, config) and
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
@@ -4467,9 +4469,9 @@ private module FlowExploration {
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(int i, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
p.isParameterOf(callable, i) and
exists(ParameterPosition pos, DataFlowCallable callable |
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
sc2 = TSummaryCtx2Some(ap)
|
@@ -4633,22 +4635,23 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
RevPartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeRev mid, ParamNodeEx p |
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
p.getPosition() = pos and
p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
ap = mid.getAp() and
config = mid.getConfiguration()
config = mid.getConfiguration() and
parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
Configuration config
) {
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
@@ -4661,7 +4664,7 @@ private module FlowExploration {
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
exists(DataFlowCall call, ArgumentPosition pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)

View File

@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
tupleLimit = 1000
}
/**
* Holds if `arg` is an argument of `call` with an argument position that matches
* parameter position `ppos`.
*/
pragma[noinline]
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
exists(ArgumentPosition apos |
arg.argumentOf(call, apos) and
parameterMatch(ppos, apos)
)
}
/**
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
* currently excludes read-steps, store-steps, and flow-through.
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
pragma[noinline]
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallable(call), ppos)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
pragma[noinline]
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), ppos)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamNonLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
exists(ParameterPosition ppos |
viableParamLambda(call, ppos, p) and
argumentPositionMatch(call, arg, ppos)
)
}
@@ -322,7 +336,7 @@ private module Cached {
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
)
}
@@ -330,7 +344,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
exists(ParamNode p, ParameterPosition pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -352,11 +366,13 @@ private module Cached {
}
cached
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
isParameterNode(p, c, pos)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
isArgumentNode(n, call, pos)
}
/**
@@ -374,12 +390,12 @@ private module Cached {
}
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
* The instance parameter is considered to have index `-1`.
* Holds if `p` is the parameter of a viable dispatch target of `call`,
* and `p` has position `ppos`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
p.isParameterOf(viableCallableExt(call), ppos)
}
/**
@@ -388,9 +404,9 @@ private module Cached {
*/
cached
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
exists(ParameterPosition ppos |
viableParam(call, ppos, p) and
argumentPositionMatch(call, arg, ppos) and
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -862,7 +878,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
* position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
}
/** A data-flow node that represents a call argument. */
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
argumentNode(this, call, pos)
}
}
/**
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
private int pos;
private ParameterPosition pos;
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
int getPosition() { result = pos }
ParameterPosition getPosition() { result = pos }
pragma[nomagic]
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
override string toString() { result = "param update " + pos }
}

View File

@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
p.isParameterOf(c, pos)
}
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
arg.argumentOf(c, pos)
}
/**
* A data flow node that occurs as the argument of a call and is passed as-is