mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
Merge pull request #7260 from hvitved/dataflow/argument-parameter-matching
Data flow: Introduce `ParameterPosition` and `ArgumentPosition`
This commit is contained in:
@@ -183,6 +183,22 @@ private module DispatchImpl {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private int parameterPosition() { result in [-1, any(Parameter p).getPosition()] }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { this = parameterPosition() }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { this = parameterPosition() }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
}
|
||||
|
||||
import DispatchImpl
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -310,6 +310,8 @@ private class ImplicitExprPostUpdate extends ImplicitPostUpdateNode, TImplicitEx
|
||||
}
|
||||
|
||||
module Private {
|
||||
private import DataFlowDispatch
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) {
|
||||
result.asCallable() = n.asExpr().getEnclosingCallable() or
|
||||
@@ -324,10 +326,15 @@ module Private {
|
||||
}
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) {
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c.asCallable(), 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
|
||||
* to the callable. Arguments that are wrapped in an implicit varargs array
|
||||
|
||||
@@ -26,9 +26,13 @@ module Public {
|
||||
string toString() {
|
||||
exists(Content c | this = TContentSummaryComponent(c) and result = c.toString())
|
||||
or
|
||||
exists(int i | this = TParameterSummaryComponent(i) and result = "parameter " + i)
|
||||
exists(ArgumentPosition pos |
|
||||
this = TParameterSummaryComponent(pos) and result = "parameter " + pos
|
||||
)
|
||||
or
|
||||
exists(int i | this = TArgumentSummaryComponent(i) and result = "argument " + i)
|
||||
exists(ParameterPosition pos |
|
||||
this = TArgumentSummaryComponent(pos) and result = "argument " + pos
|
||||
)
|
||||
or
|
||||
exists(ReturnKind rk | this = TReturnSummaryComponent(rk) and result = "return (" + rk + ")")
|
||||
}
|
||||
@@ -39,11 +43,11 @@ module Public {
|
||||
/** Gets a summary component for content `c`. */
|
||||
SummaryComponent content(Content c) { result = TContentSummaryComponent(c) }
|
||||
|
||||
/** Gets a summary component for parameter `i`. */
|
||||
SummaryComponent parameter(int i) { result = TParameterSummaryComponent(i) }
|
||||
/** Gets a summary component for a parameter at position `pos`. */
|
||||
SummaryComponent parameter(ArgumentPosition pos) { result = TParameterSummaryComponent(pos) }
|
||||
|
||||
/** Gets a summary component for argument `i`. */
|
||||
SummaryComponent argument(int i) { result = TArgumentSummaryComponent(i) }
|
||||
/** Gets a summary component for an argument at position `pos`. */
|
||||
SummaryComponent argument(ParameterPosition pos) { result = TArgumentSummaryComponent(pos) }
|
||||
|
||||
/** Gets a summary component for a return of kind `rk`. */
|
||||
SummaryComponent return(ReturnKind rk) { result = TReturnSummaryComponent(rk) }
|
||||
@@ -120,8 +124,10 @@ module Public {
|
||||
result = TConsSummaryComponentStack(head, tail)
|
||||
}
|
||||
|
||||
/** Gets a singleton stack for argument `i`. */
|
||||
SummaryComponentStack argument(int i) { result = singleton(SummaryComponent::argument(i)) }
|
||||
/** Gets a singleton stack for an argument at position `pos`. */
|
||||
SummaryComponentStack argument(ParameterPosition pos) {
|
||||
result = singleton(SummaryComponent::argument(pos))
|
||||
}
|
||||
|
||||
/** Gets a singleton stack representing a return of kind `rk`. */
|
||||
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
|
||||
@@ -137,9 +143,15 @@ module Public {
|
||||
or
|
||||
noComponentSpecificCsv(sc) and
|
||||
(
|
||||
exists(int i | sc = TParameterSummaryComponent(i) and result = "Parameter[" + i + "]")
|
||||
exists(ArgumentPosition pos |
|
||||
sc = TParameterSummaryComponent(pos) and
|
||||
result = "Parameter[" + getArgumentPositionCsv(pos) + "]"
|
||||
)
|
||||
or
|
||||
exists(int i | sc = TArgumentSummaryComponent(i) and result = "Argument[" + i + "]")
|
||||
exists(ParameterPosition pos |
|
||||
sc = TArgumentSummaryComponent(pos) and
|
||||
result = "Argument[" + getParameterPositionCsv(pos) + "]"
|
||||
)
|
||||
or
|
||||
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
|
||||
)
|
||||
@@ -201,10 +213,10 @@ module Public {
|
||||
|
||||
/**
|
||||
* Holds if values stored inside `content` are cleared on objects passed as
|
||||
* the `i`th argument to this callable.
|
||||
* arguments at position `pos` to this callable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate clearsContent(int i, Content content) { none() }
|
||||
predicate clearsContent(ParameterPosition pos, Content content) { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,11 +229,11 @@ module Private {
|
||||
|
||||
newtype TSummaryComponent =
|
||||
TContentSummaryComponent(Content c) or
|
||||
TParameterSummaryComponent(int i) { parameterPosition(i) } or
|
||||
TArgumentSummaryComponent(int i) { parameterPosition(i) } or
|
||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||
TReturnSummaryComponent(ReturnKind rk)
|
||||
|
||||
private TSummaryComponent thisParam() {
|
||||
private TParameterSummaryComponent thisParam() {
|
||||
result = TParameterSummaryComponent(instanceParameterPosition())
|
||||
}
|
||||
|
||||
@@ -285,9 +297,9 @@ module Private {
|
||||
|
||||
/**
|
||||
* Holds if `c` has a flow summary from `input` to `arg`, where `arg`
|
||||
* writes to (contents of) the `i`th argument, and `c` has a
|
||||
* value-preserving flow summary from the `i`th argument to a return value
|
||||
* (`return`).
|
||||
* writes to (contents of) arguments at position `pos`, and `c` has a
|
||||
* value-preserving flow summary from the arguments at position `pos`
|
||||
* to a return value (`return`).
|
||||
*
|
||||
* In such a case, we derive flow from `input` to (contents of) the return
|
||||
* value.
|
||||
@@ -302,10 +314,10 @@ module Private {
|
||||
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
|
||||
SummaryComponentStack return, boolean preservesValue
|
||||
) {
|
||||
exists(int i |
|
||||
exists(ParameterPosition pos |
|
||||
summary(c, input, arg, preservesValue) and
|
||||
isContentOfArgument(arg, i) and
|
||||
summary(c, SummaryComponentStack::singleton(TArgumentSummaryComponent(i)), return, true) and
|
||||
isContentOfArgument(arg, pos) and
|
||||
summary(c, SummaryComponentStack::argument(pos), return, true) and
|
||||
return.bottom() = TReturnSummaryComponent(_)
|
||||
)
|
||||
}
|
||||
@@ -330,10 +342,10 @@ module Private {
|
||||
s.head() = TParameterSummaryComponent(_) and exists(s.tail())
|
||||
}
|
||||
|
||||
private predicate isContentOfArgument(SummaryComponentStack s, int i) {
|
||||
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail(), i)
|
||||
private predicate isContentOfArgument(SummaryComponentStack s, ParameterPosition pos) {
|
||||
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail(), pos)
|
||||
or
|
||||
s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(i))
|
||||
s = SummaryComponentStack::argument(pos)
|
||||
}
|
||||
|
||||
private predicate outputState(SummarizedCallable c, SummaryComponentStack s) {
|
||||
@@ -364,8 +376,8 @@ module Private {
|
||||
private newtype TSummaryNodeState =
|
||||
TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or
|
||||
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or
|
||||
TSummaryNodeClearsContentState(int i, boolean post) {
|
||||
any(SummarizedCallable sc).clearsContent(i, _) and post in [false, true]
|
||||
TSummaryNodeClearsContentState(ParameterPosition pos, boolean post) {
|
||||
any(SummarizedCallable sc).clearsContent(pos, _) and post in [false, true]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,21 +426,23 @@ module Private {
|
||||
result = "to write: " + s
|
||||
)
|
||||
or
|
||||
exists(int i, boolean post, string postStr |
|
||||
this = TSummaryNodeClearsContentState(i, post) and
|
||||
exists(ParameterPosition pos, boolean post, string postStr |
|
||||
this = TSummaryNodeClearsContentState(pos, post) and
|
||||
(if post = true then postStr = " (post)" else postStr = "") and
|
||||
result = "clear: " + i + postStr
|
||||
result = "clear: " + pos + postStr
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `state` represents having read the `i`th argument for `c`. In this case
|
||||
* we are not synthesizing a data-flow node, but instead assume that a relevant
|
||||
* parameter node already exists.
|
||||
* Holds if `state` represents having read from a parameter at position
|
||||
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
|
||||
* but instead assume that a relevant parameter node already exists.
|
||||
*/
|
||||
private predicate parameterReadState(SummarizedCallable c, SummaryNodeState state, int i) {
|
||||
state.isInputState(c, SummaryComponentStack::argument(i))
|
||||
private predicate parameterReadState(
|
||||
SummarizedCallable c, SummaryNodeState state, ParameterPosition pos
|
||||
) {
|
||||
state.isInputState(c, SummaryComponentStack::argument(pos))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,9 +455,9 @@ module Private {
|
||||
or
|
||||
state.isOutputState(c, _)
|
||||
or
|
||||
exists(int i |
|
||||
c.clearsContent(i, _) and
|
||||
state = TSummaryNodeClearsContentState(i, _)
|
||||
exists(ParameterPosition pos |
|
||||
c.clearsContent(pos, _) and
|
||||
state = TSummaryNodeClearsContentState(pos, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -452,9 +466,9 @@ module Private {
|
||||
exists(SummaryNodeState state | state.isInputState(c, s) |
|
||||
result = summaryNode(c, state)
|
||||
or
|
||||
exists(int i |
|
||||
parameterReadState(c, state, i) and
|
||||
result.(ParamNode).isParameterOf(c, i)
|
||||
exists(ParameterPosition pos |
|
||||
parameterReadState(c, state, pos) and
|
||||
result.(ParamNode).isParameterOf(c, pos)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -468,20 +482,20 @@ module Private {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a write targets `post`, which is a post-update node for the `i`th
|
||||
* parameter of `c`.
|
||||
* Holds if a write targets `post`, which is a post-update node for a
|
||||
* parameter at position `pos` in `c`.
|
||||
*/
|
||||
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, int i) {
|
||||
post = summaryNodeOutputState(c, SummaryComponentStack::argument(i))
|
||||
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
|
||||
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
|
||||
}
|
||||
|
||||
/** Holds if a parameter node is required for the `i`th parameter of `c`. */
|
||||
predicate summaryParameterNodeRange(SummarizedCallable c, int i) {
|
||||
parameterReadState(c, _, i)
|
||||
/** Holds if a parameter node at position `pos` is required for `c`. */
|
||||
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
|
||||
parameterReadState(c, _, pos)
|
||||
or
|
||||
isParameterPostUpdate(_, c, i)
|
||||
isParameterPostUpdate(_, c, pos)
|
||||
or
|
||||
c.clearsContent(i, _)
|
||||
c.clearsContent(pos, _)
|
||||
}
|
||||
|
||||
private predicate callbackOutput(
|
||||
@@ -493,10 +507,10 @@ module Private {
|
||||
}
|
||||
|
||||
private predicate callbackInput(
|
||||
SummarizedCallable c, SummaryComponentStack s, Node receiver, int i
|
||||
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
|
||||
) {
|
||||
any(SummaryNodeState state).isOutputState(c, s) and
|
||||
s.head() = TParameterSummaryComponent(i) and
|
||||
s.head() = TParameterSummaryComponent(pos) and
|
||||
receiver = summaryNodeInputState(c, s.drop(1))
|
||||
}
|
||||
|
||||
@@ -547,17 +561,17 @@ module Private {
|
||||
result = getReturnType(c, rk)
|
||||
)
|
||||
or
|
||||
exists(int i | head = TParameterSummaryComponent(i) |
|
||||
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
|
||||
result =
|
||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.drop(1))), i)
|
||||
s.drop(1))), pos)
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable c, int i, ParamNode p |
|
||||
n = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and
|
||||
p.isParameterOf(c, i) and
|
||||
exists(SummarizedCallable c, ParameterPosition pos, ParamNode p |
|
||||
n = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
||||
p.isParameterOf(c, pos) and
|
||||
result = getNodeType(p)
|
||||
)
|
||||
}
|
||||
@@ -571,10 +585,10 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if summary node `arg` is the `i`th argument of call `c`. */
|
||||
predicate summaryArgumentNode(DataFlowCall c, Node arg, int i) {
|
||||
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
|
||||
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
|
||||
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
|
||||
callbackInput(callable, s, receiver, i) and
|
||||
callbackInput(callable, s, receiver, pos) and
|
||||
arg = summaryNodeOutputState(callable, s) and
|
||||
c = summaryDataFlowCall(receiver)
|
||||
)
|
||||
@@ -582,12 +596,12 @@ module Private {
|
||||
|
||||
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
|
||||
predicate summaryPostUpdateNode(Node post, Node pre) {
|
||||
exists(SummarizedCallable c, int i |
|
||||
isParameterPostUpdate(post, c, i) and
|
||||
pre.(ParamNode).isParameterOf(c, i)
|
||||
exists(SummarizedCallable c, ParameterPosition pos |
|
||||
isParameterPostUpdate(post, c, pos) and
|
||||
pre.(ParamNode).isParameterOf(c, pos)
|
||||
or
|
||||
pre = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and
|
||||
post = summaryNode(c, TSummaryNodeClearsContentState(i, true))
|
||||
pre = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
||||
post = summaryNode(c, TSummaryNodeClearsContentState(pos, true))
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable callable, SummaryComponentStack s |
|
||||
@@ -610,13 +624,13 @@ module Private {
|
||||
* node, and back out to `p`.
|
||||
*/
|
||||
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
|
||||
exists(SummarizedCallable c, int i | p.isParameterOf(c, i) |
|
||||
c.clearsContent(i, _)
|
||||
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
|
||||
c.clearsContent(ppos, _)
|
||||
or
|
||||
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
|
||||
summary(c, inputContents, outputContents, _) and
|
||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i)) and
|
||||
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i))
|
||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
|
||||
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos))
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -641,9 +655,9 @@ module Private {
|
||||
preservesValue = false and not summary(c, inputContents, outputContents, true)
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable c, int i |
|
||||
pred.(ParamNode).isParameterOf(c, i) and
|
||||
succ = summaryNode(c, TSummaryNodeClearsContentState(i, _)) and
|
||||
exists(SummarizedCallable c, ParameterPosition pos |
|
||||
pred.(ParamNode).isParameterOf(c, pos) and
|
||||
succ = summaryNode(c, TSummaryNodeClearsContentState(pos, _)) and
|
||||
preservesValue = true
|
||||
)
|
||||
}
|
||||
@@ -692,12 +706,20 @@ module Private {
|
||||
* node where field `b` is cleared).
|
||||
*/
|
||||
predicate summaryClearsContent(Node n, Content c) {
|
||||
exists(SummarizedCallable sc, int i |
|
||||
n = summaryNode(sc, TSummaryNodeClearsContentState(i, true)) and
|
||||
sc.clearsContent(i, c)
|
||||
exists(SummarizedCallable sc, ParameterPosition pos |
|
||||
n = summaryNode(sc, TSummaryNodeClearsContentState(pos, true)) and
|
||||
sc.clearsContent(pos, c)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate viableParam(
|
||||
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
|
||||
) {
|
||||
p.isParameterOf(sc, ppos) and
|
||||
sc = viableCallable(call)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared inside a
|
||||
* callable to which `arg` is an argument.
|
||||
@@ -706,18 +728,18 @@ module Private {
|
||||
* `arg` (see comment for `summaryClearsContent`).
|
||||
*/
|
||||
predicate summaryClearsContentArg(ArgNode arg, Content c) {
|
||||
exists(DataFlowCall call, int i |
|
||||
viableCallable(call).(SummarizedCallable).clearsContent(i, c) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, _) and
|
||||
sc.clearsContent(ppos, c)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||
exists(DataFlowCall call, int pos, SummarizedCallable callable |
|
||||
arg.argumentOf(call, pos) and
|
||||
viableCallable(call) = callable and
|
||||
result.isParameterOf(callable, pos) and
|
||||
exists(DataFlowCall call, ParameterPosition ppos, SummarizedCallable sc |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, result) and
|
||||
out = rk.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
@@ -795,39 +817,33 @@ module Private {
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as parameter `n`. */
|
||||
predicate parseParam(string c, int n) {
|
||||
predicate parseParam(string c, ArgumentPosition pos) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\]", 1).toInt() = n
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
|
||||
n = [n1 .. n2]
|
||||
)
|
||||
exists(string body |
|
||||
body = c.regexpCapture("Parameter\\[([^\\]]*)\\]", 1) and
|
||||
pos = parseParamBody(body)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as argument `n`. */
|
||||
predicate parseArg(string c, int n) {
|
||||
predicate parseArg(string c, ParameterPosition pos) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\]", 1).toInt() = n
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
|
||||
n = [n1 .. n2]
|
||||
)
|
||||
exists(string body |
|
||||
body = c.regexpCapture("Argument\\[([^\\]]*)\\]", 1) and
|
||||
pos = parseArgBody(body)
|
||||
)
|
||||
}
|
||||
|
||||
private SummaryComponent interpretComponent(string c) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
exists(int pos | parseArg(c, pos) and result = SummaryComponent::argument(pos))
|
||||
exists(ParameterPosition pos |
|
||||
parseArg(c, pos) and result = SummaryComponent::argument(pos)
|
||||
)
|
||||
or
|
||||
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
|
||||
exists(ArgumentPosition pos |
|
||||
parseParam(c, pos) and result = SummaryComponent::parameter(pos)
|
||||
)
|
||||
or
|
||||
c = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
@@ -934,14 +950,18 @@ module Private {
|
||||
interpretOutput(output, idx + 1, ref, mid) and
|
||||
specSplit(output, c, idx)
|
||||
|
|
||||
exists(int pos |
|
||||
node.asNode().(PostUpdateNode).getPreUpdateNode().(ArgNode).argumentOf(mid.asCall(), pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(PostUpdateNode).getPreUpdateNode().(ArgNode).argumentOf(mid.asCall(), apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
c = "Argument" or parseArg(c, ppos)
|
||||
)
|
||||
or
|
||||
exists(int pos | node.asNode().(ParamNode).isParameterOf(mid.asCallable(), pos) |
|
||||
c = "Parameter" or parseParam(c, pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(ParamNode).isParameterOf(mid.asCallable(), ppos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Parameter" or parseParam(c, apos)
|
||||
)
|
||||
or
|
||||
c = "ReturnValue" and
|
||||
@@ -960,8 +980,11 @@ module Private {
|
||||
interpretInput(input, idx + 1, ref, mid) and
|
||||
specSplit(input, c, idx)
|
||||
|
|
||||
exists(int pos | node.asNode().(ArgNode).argumentOf(mid.asCall(), pos) |
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(ArgNode).argumentOf(mid.asCall(), apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Argument" or parseArg(c, ppos)
|
||||
)
|
||||
or
|
||||
exists(ReturnNodeExt ret |
|
||||
@@ -1117,9 +1140,9 @@ module Private {
|
||||
b.asCall() = summaryDataFlowCall(a.asNode()) and
|
||||
value = "receiver"
|
||||
or
|
||||
exists(int i |
|
||||
summaryArgumentNode(b.asCall(), a.asNode(), i) and
|
||||
value = "argument (" + i + ")"
|
||||
exists(ArgumentPosition pos |
|
||||
summaryArgumentNode(b.asCall(), a.asNode(), pos) and
|
||||
value = "argument (" + pos + ")"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
private import java
|
||||
private import DataFlowDispatch
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
private import FlowSummaryImpl::Private
|
||||
@@ -13,9 +14,6 @@ private module FlowSummaries {
|
||||
private import semmle.code.java.dataflow.FlowSummary as F
|
||||
}
|
||||
|
||||
/** Holds is `i` is a valid parameter position. */
|
||||
predicate parameterPosition(int i) { i in [-1 .. any(Parameter p).getPosition()] }
|
||||
|
||||
/** Gets the parameter position of the instance parameter. */
|
||||
int instanceParameterPosition() { result = -1 }
|
||||
|
||||
@@ -98,6 +96,12 @@ string getComponentSpecificCsv(SummaryComponent sc) {
|
||||
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecificCsv(c))
|
||||
}
|
||||
|
||||
/** Gets the textual representation of a parameter position in the format used for flow summaries. */
|
||||
string getParameterPositionCsv(ParameterPosition pos) { result = pos.toString() }
|
||||
|
||||
/** Gets the textual representation of an argument position in the format used for flow summaries. */
|
||||
string getArgumentPositionCsv(ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
class SourceOrSinkElement = Top;
|
||||
|
||||
/**
|
||||
@@ -189,3 +193,22 @@ predicate interpretInputSpecific(string c, InterpretNode mid, InterpretNode n) {
|
||||
n.asNode().asExpr() = fw.getRHS()
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
private int parsePosition(string s) {
|
||||
result = s.regexpCapture("([-0-9]+)", 1).toInt()
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 1).toInt() = n1 and
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 2).toInt() = n2 and
|
||||
result in [n1 .. n2]
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the argument position obtained by parsing `X` in `Parameter[X]`. */
|
||||
bindingset[s]
|
||||
ArgumentPosition parseParamBody(string s) { result = parsePosition(s) }
|
||||
|
||||
/** Gets the parameter position obtained by parsing `X` in `Argument[X]`. */
|
||||
bindingset[s]
|
||||
ParameterPosition parseArgBody(string s) { result = parsePosition(s) }
|
||||
|
||||
Reference in New Issue
Block a user