mirror of
https://github.com/github/codeql.git
synced 2026-01-29 22:32:58 +01:00
Sync data-flow libraries
As of 2021-05-12
This commit is contained in:
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
(
|
||||
simpleLocalFlowStep(node1, node2) or
|
||||
reverseStepThroughInputOutputAlias(node1, node2)
|
||||
) and
|
||||
simpleLocalFlowStepExt(node1, node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
|
||||
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
|
||||
*/
|
||||
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
jumpStep(node1, node2) and
|
||||
jumpStepCached(node1, node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
fwdFlow(arg, cc, config) and
|
||||
viableParamArg(call, _, arg)
|
||||
)
|
||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
||||
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||
) {
|
||||
viableParamArg(call, p, arg) and
|
||||
fwdFlow(arg, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||
exists(ParamNode p |
|
||||
revFlow(p, toReturn, config) and
|
||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
|
||||
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
|
||||
revFlowIn(call, arg, true, config)
|
||||
}
|
||||
|
||||
@@ -597,7 +592,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate viableParamArgNodeCand1(
|
||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
||||
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||
) {
|
||||
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||
Stage1::revFlow(arg, config)
|
||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand1(
|
||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
|
||||
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand1(
|
||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||
exists(int b, int j |
|
||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
)
|
||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand2(
|
||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
castNode(this) or
|
||||
clearsContentCached(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
||||
config.isSource(node) or
|
||||
jumpStep(_, node, config) or
|
||||
additionalJumpStep(_, node, config) or
|
||||
node instanceof ParameterNode or
|
||||
node instanceof ParamNode or
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||
LocalCallContext cc
|
||||
) {
|
||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
(
|
||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||
(
|
||||
localFlowStepNodeCand1(node1, node2, config) and
|
||||
preservesValue = true and
|
||||
t = getNodeType(node1)
|
||||
t = getNodeDataFlowType(node1)
|
||||
or
|
||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||
preservesValue = false and
|
||||
t = getNodeType(node2)
|
||||
t = getNodeDataFlowType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||
or
|
||||
exists(Node mid |
|
||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getNodeType(node2) and
|
||||
t = getNodeDataFlowType(node2) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||
)
|
||||
)
|
||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
||||
bindingset[node, ap]
|
||||
private predicate filter(Node node, Ap ap) {
|
||||
not ap.isClearedAt(node) and
|
||||
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||
else any()
|
||||
}
|
||||
|
||||
bindingset[ap, contentType]
|
||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCall(
|
||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
|
||||
private newtype TSummaryCtx =
|
||||
TSummaryCtxNone() or
|
||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
||||
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
||||
}
|
||||
|
||||
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
|
||||
|
||||
/** A summary context from which a flow summary can be generated. */
|
||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
private ParameterNode p;
|
||||
private ParamNode p;
|
||||
private AccessPath ap;
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
ap = TAccessPathNil(getNodeType(node))
|
||||
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
exists(PathNodeMid mid |
|
||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
nodeIsHidden(this.getNode()) and
|
||||
hiddenNode(this.getNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
}
|
||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TAccessPathNil(getNodeType(node))
|
||||
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||
or
|
||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||
sc = mid.getSummaryCtx()
|
||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
arg = mid.getNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
)
|
||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
||||
* respectively.
|
||||
*/
|
||||
private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TSummaryCtx1 =
|
||||
TSummaryCtx1None() or
|
||||
TSummaryCtx1Param(ParameterNode p)
|
||||
TSummaryCtx1Param(ParamNode p)
|
||||
|
||||
private newtype TSummaryCtx2 =
|
||||
TSummaryCtx2None() or
|
||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
||||
cc instanceof CallContextAny and
|
||||
sc1 = TSummaryCtx1None() and
|
||||
sc2 = TSummaryCtx2None() and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not clearsContentCached(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
not clearsContentCached(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||
else any()
|
||||
)
|
||||
}
|
||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||
(
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
config = mid.getConfiguration()
|
||||
)
|
||||
or
|
||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
||||
sc1 = TSummaryCtx1None() and
|
||||
sc2 = TSummaryCtx2None() and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
apConsFwd(ap, tc, ap0, config) and
|
||||
compatibleTypes(ap.getType(), getNodeType(node))
|
||||
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||
)
|
||||
or
|
||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
||||
@@ -3924,7 +3915,7 @@ private module FlowExploration {
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
arg = mid.getNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
|
||||
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||
)
|
||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
||||
apConsRev(ap, c, ap0, config)
|
||||
)
|
||||
or
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
mid.getNode() = p and
|
||||
viableParamArg(_, p, node) and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
||||
exists(PartialPathNodeRev mid, ParamNode p |
|
||||
mid.getNode() = p and
|
||||
p.isParameterOf(_, pos) and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
||||
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
|
||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
(
|
||||
simpleLocalFlowStep(node1, node2) or
|
||||
reverseStepThroughInputOutputAlias(node1, node2)
|
||||
) and
|
||||
simpleLocalFlowStepExt(node1, node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
|
||||
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
|
||||
*/
|
||||
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
jumpStep(node1, node2) and
|
||||
jumpStepCached(node1, node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
fwdFlow(arg, cc, config) and
|
||||
viableParamArg(call, _, arg)
|
||||
)
|
||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate viableParamArgNodeCandFwd1(
|
||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
||||
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||
) {
|
||||
viableParamArg(call, p, arg) and
|
||||
fwdFlow(arg, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||
exists(ParamNode p |
|
||||
revFlow(p, toReturn, config) and
|
||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
|
||||
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
|
||||
revFlowIn(call, arg, true, config)
|
||||
}
|
||||
|
||||
@@ -597,7 +592,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate viableParamArgNodeCand1(
|
||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
||||
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||
) {
|
||||
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||
Stage1::revFlow(arg, config)
|
||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand1(
|
||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
|
||||
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
|
||||
) {
|
||||
viableParamArgNodeCand1(call, p, arg, config) and
|
||||
Stage1::revFlow(p, config) and
|
||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand1(
|
||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||
exists(int b, int j |
|
||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
)
|
||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCallNodeCand2(
|
||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
||||
*/
|
||||
private class FlowCheckNode extends Node {
|
||||
FlowCheckNode() {
|
||||
this instanceof CastNode or
|
||||
clearsContent(this, _)
|
||||
castNode(this) or
|
||||
clearsContentCached(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
||||
config.isSource(node) or
|
||||
jumpStep(_, node, config) or
|
||||
additionalJumpStep(_, node, config) or
|
||||
node instanceof ParameterNode or
|
||||
node instanceof ParamNode or
|
||||
node instanceof OutNodeExt or
|
||||
store(_, _, node, _) or
|
||||
read(_, _, node) or
|
||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||
LocalCallContext cc
|
||||
) {
|
||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
(
|
||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||
(
|
||||
localFlowStepNodeCand1(node1, node2, config) and
|
||||
preservesValue = true and
|
||||
t = getNodeType(node1)
|
||||
t = getNodeDataFlowType(node1)
|
||||
or
|
||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||
preservesValue = false and
|
||||
t = getNodeType(node2)
|
||||
t = getNodeDataFlowType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||
or
|
||||
exists(Node mid |
|
||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||
not mid instanceof FlowCheckNode and
|
||||
preservesValue = false and
|
||||
t = getNodeType(node2) and
|
||||
t = getNodeDataFlowType(node2) and
|
||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||
)
|
||||
)
|
||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
||||
bindingset[node, ap]
|
||||
private predicate filter(Node node, Ap ap) {
|
||||
not ap.isClearedAt(node) and
|
||||
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||
else any()
|
||||
}
|
||||
|
||||
bindingset[ap, contentType]
|
||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowIntoCall(
|
||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||
) {
|
||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowIn(
|
||||
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
||||
private predicate fwdFlowIsEntered(
|
||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIn(
|
||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
||||
Configuration config
|
||||
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
||||
exists(ParamNode p, boolean allowsFieldFlow |
|
||||
revFlow(p, toReturn, returnAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revFlowInToReturn(
|
||||
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||
}
|
||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate parameterFlow(
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
|
||||
private newtype TSummaryCtx =
|
||||
TSummaryCtxNone() or
|
||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
||||
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
||||
}
|
||||
|
||||
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
|
||||
|
||||
/** A summary context from which a flow summary can be generated. */
|
||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
private ParameterNode p;
|
||||
private ParamNode p;
|
||||
private AccessPath ap;
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
ap = TAccessPathNil(getNodeType(node))
|
||||
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||
or
|
||||
// ... or a step from an existing PathNode to another node.
|
||||
exists(PathNodeMid mid |
|
||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
nodeIsHidden(this.getNode()) and
|
||||
hiddenNode(this.getNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
}
|
||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
cc instanceof CallContextAny and
|
||||
sc instanceof SummaryCtxNone and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TAccessPathNil(getNodeType(node))
|
||||
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||
or
|
||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||
sc = mid.getSummaryCtx()
|
||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
arg = mid.getNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
)
|
||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
||||
* respectively.
|
||||
*/
|
||||
private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
||||
|
||||
private newtype TSummaryCtx1 =
|
||||
TSummaryCtx1None() or
|
||||
TSummaryCtx1Param(ParameterNode p)
|
||||
TSummaryCtx1Param(ParamNode p)
|
||||
|
||||
private newtype TSummaryCtx2 =
|
||||
TSummaryCtx2None() or
|
||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
||||
cc instanceof CallContextAny and
|
||||
sc1 = TSummaryCtx1None() and
|
||||
sc2 = TSummaryCtx2None() and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not clearsContentCached(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
||||
exists(PartialPathNodeFwd mid |
|
||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not clearsContent(node, ap.getHead().getContent()) and
|
||||
not clearsContentCached(node, ap.getHead().getContent()) and
|
||||
if node instanceof CastingNode
|
||||
then compatibleTypes(getNodeType(node), ap.getType())
|
||||
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||
else any()
|
||||
)
|
||||
}
|
||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
||||
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||
(
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
config = mid.getConfiguration()
|
||||
)
|
||||
or
|
||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
||||
sc1 = TSummaryCtx1None() and
|
||||
sc2 = TSummaryCtx2None() and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getNodeType(node)) and
|
||||
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
apConsFwd(ap, tc, ap0, config) and
|
||||
compatibleTypes(ap.getType(), getNodeType(node))
|
||||
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||
)
|
||||
or
|
||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
||||
@@ -3924,7 +3915,7 @@ private module FlowExploration {
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
arg = mid.getNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
|
||||
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||
)
|
||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
||||
apConsRev(ap, c, ap0, config)
|
||||
)
|
||||
or
|
||||
exists(ParameterNode p |
|
||||
exists(ParamNode p |
|
||||
mid.getNode() = p and
|
||||
viableParamArg(_, p, node) and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
||||
exists(PartialPathNodeRev mid, ParamNode p |
|
||||
mid.getNode() = p and
|
||||
p.isParameterOf(_, pos) and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
||||
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
|
||||
@@ -35,22 +35,22 @@ 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, ParameterNode p) {
|
||||
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
}
|
||||
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), i)
|
||||
}
|
||||
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamNonLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
||||
boolean toJump, DataFlowCallOption lastCall
|
||||
) {
|
||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
||||
then compatibleTypes(t, getNodeType(node))
|
||||
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||
else any()
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
||||
boolean toJump, DataFlowCallOption lastCall
|
||||
) {
|
||||
lambdaCall(lambdaCall, kind, node) and
|
||||
t = getNodeType(node) and
|
||||
t = getNodeDataFlowType(node) and
|
||||
toReturn = false and
|
||||
toJump = false and
|
||||
lastCall = TDataFlowCallNone()
|
||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||
|
|
||||
preservesValue = false and
|
||||
t = getNodeType(node)
|
||||
t = getNodeDataFlowType(node)
|
||||
or
|
||||
preservesValue = true and
|
||||
t = t0
|
||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
||||
toJump = true and
|
||||
lastCall = TDataFlowCallNone()
|
||||
|
|
||||
jumpStep(node, mid) and
|
||||
jumpStepCached(node, mid) and
|
||||
t = t0
|
||||
or
|
||||
exists(boolean preservesValue |
|
||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||
|
|
||||
preservesValue = false and
|
||||
t = getNodeType(node)
|
||||
t = getNodeDataFlowType(node)
|
||||
or
|
||||
preservesValue = true and
|
||||
t = t0
|
||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
|
||||
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
|
||||
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||
(
|
||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate revLambdaFlowIn(
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||
DataFlowCallOption lastCall
|
||||
) {
|
||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
|
||||
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
|
||||
* collapsing the two stages.
|
||||
*/
|
||||
cached
|
||||
predicate forceCachingInSameStage() { any() }
|
||||
|
||||
cached
|
||||
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
|
||||
|
||||
cached
|
||||
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
|
||||
c = call.getEnclosingCallable()
|
||||
}
|
||||
|
||||
cached
|
||||
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
|
||||
|
||||
cached
|
||||
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
|
||||
|
||||
cached
|
||||
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
|
||||
|
||||
cached
|
||||
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
|
||||
|
||||
cached
|
||||
predicate outNodeExt(Node n) {
|
||||
n instanceof OutNode
|
||||
or
|
||||
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hiddenNode(Node n) { nodeIsHidden(n) }
|
||||
|
||||
cached
|
||||
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
|
||||
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
|
||||
or
|
||||
exists(ArgNode arg |
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate returnNodeExt(Node n, ReturnKindExt k) {
|
||||
k = TValueReturn(n.(ReturnNode).getKind())
|
||||
or
|
||||
exists(ParamNode p, int pos |
|
||||
parameterValueFlowsToPreUpdate(p, n) and
|
||||
p.isParameterOf(_, pos) and
|
||||
k = TParamUpdate(pos)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate castNode(Node n) { n instanceof CastNode }
|
||||
|
||||
cached
|
||||
predicate castingNode(Node n) {
|
||||
castNode(n) or
|
||||
n instanceof ParamNode or
|
||||
n instanceof OutNodeExt or
|
||||
// For reads, `x.f`, we want to check that the tracked type after the read (which
|
||||
// is obtained by popping the head of the access path stack) is compatible with
|
||||
// the type of `x.f`.
|
||||
read(_, _, n)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate parameterNode(Node n, DataFlowCallable c, int i) {
|
||||
n.(ParameterNode).isParameterOf(c, i)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate argumentNode(Node n, DataFlowCall call, int pos) {
|
||||
n.(ArgumentNode).argumentOf(call, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a viable target for the lambda call `call`.
|
||||
*
|
||||
@@ -261,7 +344,7 @@ private module Cached {
|
||||
* The instance parameter is considered to have index `-1`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
|
||||
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), i)
|
||||
}
|
||||
|
||||
@@ -270,11 +353,11 @@ private module Cached {
|
||||
* dispatch into account.
|
||||
*/
|
||||
cached
|
||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
||||
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParam(call, i, p) and
|
||||
arg.argumentOf(call, i) and
|
||||
compatibleTypes(getNodeType(arg), getNodeType(p))
|
||||
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -312,7 +395,7 @@ private module Cached {
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
||||
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||
p = node and
|
||||
read = false
|
||||
or
|
||||
@@ -325,30 +408,30 @@ private module Cached {
|
||||
// read
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
readStep(mid, _, node) and
|
||||
read(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
parameterValueFlowArgCand(p, arg, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read)
|
||||
)
|
||||
or
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
parameterValueFlowArgCand(p, arg, read) and
|
||||
argumentValueFlowsThroughCand(arg, node, false)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
||||
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||
parameterValueFlowCand(p, arg, read)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
||||
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
||||
}
|
||||
|
||||
@@ -360,7 +443,7 @@ private module Cached {
|
||||
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||
* node.
|
||||
*/
|
||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
||||
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlowCand(p, ret, read) and
|
||||
kind = ret.getKind()
|
||||
@@ -369,9 +452,9 @@ private module Cached {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThroughCand0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
|
||||
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
exists(ParamNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturnCand(param, kind, read)
|
||||
)
|
||||
}
|
||||
@@ -382,14 +465,14 @@ private module Cached {
|
||||
*
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
||||
*/
|
||||
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
|
||||
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate cand(ParameterNode p, Node n) {
|
||||
predicate cand(ParamNode p, Node n) {
|
||||
parameterValueFlowCand(p, n, _) and
|
||||
(
|
||||
parameterValueFlowReturnCand(p, _, _)
|
||||
@@ -416,21 +499,21 @@ private module Cached {
|
||||
* If a read step was taken, then `read` captures the `Content`, the
|
||||
* container type, and the content type.
|
||||
*/
|
||||
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
|
||||
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||
parameterValueFlow0(p, node, read) and
|
||||
if node instanceof CastingNode
|
||||
then
|
||||
// normal flow through
|
||||
read = TReadStepTypesNone() and
|
||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
||||
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||
or
|
||||
// getter
|
||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
||||
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
||||
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||
p = node and
|
||||
Cand::cand(p, _) and
|
||||
read = TReadStepTypesNone()
|
||||
@@ -447,7 +530,7 @@ private module Cached {
|
||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||
read.getContentType()) and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
||||
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||
)
|
||||
or
|
||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||
@@ -455,34 +538,32 @@ private module Cached {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlow0_0(
|
||||
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
|
||||
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
|
||||
) {
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||
argumentValueFlowsThrough(arg, read, node)
|
||||
)
|
||||
or
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
exists(ArgNode arg |
|
||||
parameterValueFlowArg(p, arg, read) and
|
||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArg(
|
||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
||||
) {
|
||||
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||
parameterValueFlow(p, arg, read) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThrough0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
|
||||
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
exists(ParamNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturn(param, kind, read)
|
||||
)
|
||||
}
|
||||
@@ -496,18 +577,18 @@ private module Cached {
|
||||
* container type, and the content type.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
||||
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||
out = getAnOutNode(call, kind)
|
||||
|
|
||||
// normal flow through
|
||||
read = TReadStepTypesNone() and
|
||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
||||
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||
or
|
||||
// getter
|
||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
||||
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -516,7 +597,7 @@ private module Cached {
|
||||
* value-preserving steps and a single read step, not taking call
|
||||
* contexts into account, thus representing a getter-step.
|
||||
*/
|
||||
predicate getterStep(ArgumentNode arg, Content c, Node out) {
|
||||
predicate getterStep(ArgNode arg, Content c, Node out) {
|
||||
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||
}
|
||||
|
||||
@@ -529,7 +610,7 @@ private module Cached {
|
||||
* container type, and the content type.
|
||||
*/
|
||||
private predicate parameterValueFlowReturn(
|
||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
||||
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||
) {
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlow(p, ret, read) and
|
||||
@@ -553,7 +634,7 @@ private module Cached {
|
||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||
mayBenefitFromCallContext(call, callable)
|
||||
or
|
||||
callable = call.getEnclosingCallable() and
|
||||
callEnclosingCallable(call, callable) and
|
||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||
}
|
||||
|
||||
@@ -611,7 +692,7 @@ private module Cached {
|
||||
mayBenefitFromCallContextExt(call, _) and
|
||||
c = viableCallableExt(call) and
|
||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
|
||||
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
|
||||
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
|
||||
ctxtgts < tgts
|
||||
)
|
||||
}
|
||||
@@ -635,8 +716,7 @@ private module Cached {
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||
}
|
||||
|
||||
@@ -644,9 +724,9 @@ private module Cached {
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
storeStep(node1, c, node2) and
|
||||
readStep(_, c, _) and
|
||||
contentType = getNodeType(node1) and
|
||||
containerType = getNodeType(node2)
|
||||
read(_, c, _) and
|
||||
contentType = getNodeDataFlowType(node1) and
|
||||
containerType = getNodeDataFlowType(node2)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
@@ -654,12 +734,15 @@ private module Cached {
|
||||
|
|
||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||
or
|
||||
readStep(n2, c, n1) and
|
||||
contentType = getNodeType(n1) and
|
||||
containerType = getNodeType(n2)
|
||||
read(n2, c, n1) and
|
||||
contentType = getNodeDataFlowType(n1) and
|
||||
containerType = getNodeDataFlowType(n2)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -678,8 +761,9 @@ private module Cached {
|
||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||
* interface.
|
||||
*/
|
||||
cached
|
||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
||||
private predicate reverseStepThroughInputOutputAlias(
|
||||
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||
) {
|
||||
exists(Node fromPre, Node toPre |
|
||||
fromPre = fromNode.getPreUpdateNode() and
|
||||
toPre = toNode.getPreUpdateNode()
|
||||
@@ -688,14 +772,20 @@ private module Cached {
|
||||
// Does the language-specific simpleLocalFlowStep already model flow
|
||||
// from function input to output?
|
||||
fromPre = getAnOutNode(c, _) and
|
||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
||||
toPre.(ArgNode).argumentOf(c, _) and
|
||||
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||
)
|
||||
or
|
||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
|
||||
simpleLocalFlowStep(node1, node2) or
|
||||
reverseStepThroughInputOutputAlias(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
@@ -704,7 +794,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -726,12 +816,12 @@ private module Cached {
|
||||
cached
|
||||
newtype TLocalFlowCallContext =
|
||||
TAnyLocalCall() or
|
||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||
|
||||
cached
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
||||
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
@@ -761,23 +851,15 @@ private module Cached {
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode extends Node {
|
||||
CastingNode() {
|
||||
this instanceof ParameterNode or
|
||||
this instanceof CastNode or
|
||||
this instanceof OutNodeExt or
|
||||
// For reads, `x.f`, we want to check that the tracked type after the read (which
|
||||
// is obtained by popping the head of the access path stack) is compatible with
|
||||
// the type of `x.f`.
|
||||
readStep(_, _, this)
|
||||
}
|
||||
CastingNode() { castingNode(this) }
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||
) {
|
||||
readStep(n1, c, n2) and
|
||||
container = getNodeType(n1) and
|
||||
content = getNodeType(n2)
|
||||
read(n1, c, n2) and
|
||||
container = getNodeDataFlowType(n1) and
|
||||
content = getNodeDataFlowType(n2)
|
||||
}
|
||||
|
||||
private newtype TReadStepTypesOption =
|
||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
||||
}
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
|
||||
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
else result instanceof LocalCallContextAny
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode extends Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* (zero-based) position.
|
||||
*/
|
||||
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
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) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt extends Node {
|
||||
ReturnNodeExt() {
|
||||
this instanceof ReturnNode or
|
||||
parameterValueFlowsToPreUpdate(_, this)
|
||||
}
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() {
|
||||
result = TValueReturn(this.(ReturnNode).getKind())
|
||||
or
|
||||
exists(ParameterNode p, int pos |
|
||||
parameterValueFlowsToPreUpdate(p, this) and
|
||||
p.isParameterOf(_, pos) and
|
||||
result = TParamUpdate(pos)
|
||||
)
|
||||
}
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() {
|
||||
this instanceof OutNode
|
||||
or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
}
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
||||
abstract string toString();
|
||||
|
||||
/** Gets a node corresponding to data flow out of `call`. */
|
||||
abstract OutNodeExt getAnOutNode(DataFlowCall call);
|
||||
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
|
||||
}
|
||||
|
||||
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
ReturnKind getKind() { result = kind }
|
||||
|
||||
override string toString() { result = kind.toString() }
|
||||
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
result = getAnOutNode(call, this.getKind())
|
||||
}
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
int getPosition() { result = pos }
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
exists(ArgumentNode arg |
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, this.getPosition())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A callable tagged with a relevant return kind. */
|
||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||
}
|
||||
|
||||
/** Gets the type of `n` used for type pruning. */
|
||||
pragma[inline]
|
||||
DataFlowType getNodeDataFlowType(Node n) {
|
||||
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||
or
|
||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||
call0.getEnclosingCallable() = callable and
|
||||
callEnclosingCallable(call0, callable) and
|
||||
cc = TReturn(c0, call0) and
|
||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||
)
|
||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
predicate read = readStep/3;
|
||||
|
||||
/** An optional Boolean value. */
|
||||
class BooleanOption extends TBooleanOption {
|
||||
string toString() {
|
||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
Reference in New Issue
Block a user