mirror of
https://github.com/github/codeql.git
synced 2026-07-07 12:35:33 +02:00
Compare commits
52 Commits
codeql-cli
...
ginsbach/w
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
065d8a60af | ||
|
|
8cdd8b6ae0 | ||
|
|
0194af9432 | ||
|
|
7974e3ad38 | ||
|
|
b05512a958 | ||
|
|
bf4d88175c | ||
|
|
8f152b7380 | ||
|
|
fc121e1cbd | ||
|
|
a247ae4357 | ||
|
|
74ae2e0857 | ||
|
|
8e371fd05a | ||
|
|
948f1d8e34 | ||
|
|
d7e560c611 | ||
|
|
3e21f479a9 | ||
|
|
d66506b0a3 | ||
|
|
48e783184c | ||
|
|
0d9a85ca6b | ||
|
|
24d8abd2c2 | ||
|
|
717070c7e4 | ||
|
|
d27316eb3e | ||
|
|
dd86da3f24 | ||
|
|
31ac6442e8 | ||
|
|
9e5a38debd | ||
|
|
d3c6093f37 | ||
|
|
c8f2937df9 | ||
|
|
67e9f06304 | ||
|
|
976ccda135 | ||
|
|
b277082462 | ||
|
|
bb97507ebc | ||
|
|
21f43252e6 | ||
|
|
0935c5a0f2 | ||
|
|
8c3980d80b | ||
|
|
c35a2b959a | ||
|
|
e8347c2c20 | ||
|
|
bd0a196a39 | ||
|
|
befc80b3cb | ||
|
|
914184f3dd | ||
|
|
0c8886967b | ||
|
|
1112c0f994 | ||
|
|
7d4feaca2f | ||
|
|
ade99c2c2b | ||
|
|
346af4f97a | ||
|
|
9738de2cb9 | ||
|
|
23113c4ff7 | ||
|
|
1bf0e01a83 | ||
|
|
4009c01558 | ||
|
|
96aa182893 | ||
|
|
8bfeae768f | ||
|
|
1a56f0b79c | ||
|
|
044c92016b | ||
|
|
98f7f70814 | ||
|
|
50c63a88c3 |
2
cpp/change-notes/2021-03-11-overflow-abs.md
Normal file
2
cpp/change-notes/2021-03-11-overflow-abs.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm
|
||||||
|
* The `cpp/tainted-arithmetic`, `cpp/arithmetic-with-extreme-values`, and `cpp/uncontrolled-arithmetic` queries now recognize more functions as returning the absolute value of their input. As a result, they produce fewer false positives.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
while(intIndex > 2)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
intIndex--;
|
||||||
|
...
|
||||||
|
} // GOOD: correct cycle
|
||||||
|
...
|
||||||
|
while(intIndex > 2)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
int intIndex;
|
||||||
|
intIndex--;
|
||||||
|
...
|
||||||
|
} // BAD: the variable used in the condition does not change.
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE qhelp PUBLIC
|
||||||
|
"-//Semmle//qhelp//EN"
|
||||||
|
"qhelp.dtd">
|
||||||
|
<qhelp>
|
||||||
|
<overview>
|
||||||
|
<p>Using variables with the same name is dangerous. However, such a situation inside the while loop can create an infinite loop exhausting resources. Requires the attention of developers.</p>
|
||||||
|
|
||||||
|
</overview>
|
||||||
|
<recommendation>
|
||||||
|
<p>We recommend not to use local variables inside a loop if their names are the same as the variables in the condition of this loop.</p>
|
||||||
|
|
||||||
|
</recommendation>
|
||||||
|
<example>
|
||||||
|
<p>The following example demonstrates an erroneous and corrected use of a local variable within a loop.</p>
|
||||||
|
<sample src="DeclarationOfVariableWithUnnecessarilyWideScope.c" />
|
||||||
|
|
||||||
|
</example>
|
||||||
|
<references>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
CERT C Coding Standard:
|
||||||
|
<a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL01-C.+Do+not+reuse+variable+names+in+subscopes">DCL01-C. Do not reuse variable names in subscopes</a>.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</references>
|
||||||
|
</qhelp>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* @name Errors When Using Variable Declaration Inside Loop
|
||||||
|
* @description Using variables with the same name is dangerous.
|
||||||
|
* However, such a situation inside the while loop can create an infinite loop exhausting resources.
|
||||||
|
* Requires the attention of developers.
|
||||||
|
* @kind problem
|
||||||
|
* @id cpp/errors-when-using-variable-declaration-inside-loop
|
||||||
|
* @problem.severity warning
|
||||||
|
* @precision medium
|
||||||
|
* @tags correctness
|
||||||
|
* security
|
||||||
|
* external/cwe/cwe-1126
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Errors when using a variable declaration inside a loop.
|
||||||
|
*/
|
||||||
|
class DangerousWhileLoop extends WhileStmt {
|
||||||
|
Expr exp;
|
||||||
|
Declaration dl;
|
||||||
|
|
||||||
|
DangerousWhileLoop() {
|
||||||
|
this = dl.getParentScope().(BlockStmt).getParent*() and
|
||||||
|
exp = this.getCondition().getAChild*() and
|
||||||
|
not exp instanceof PointerFieldAccess and
|
||||||
|
not exp instanceof ValueFieldAccess and
|
||||||
|
exp.(VariableAccess).getTarget().getName() = dl.getName() and
|
||||||
|
not exp.getParent*() instanceof FunctionCall
|
||||||
|
}
|
||||||
|
|
||||||
|
Declaration getDeclaration() { result = dl }
|
||||||
|
|
||||||
|
/** Holds when there are changes to the variables involved in the condition. */
|
||||||
|
predicate isUseThisVariable() {
|
||||||
|
exists(Variable v |
|
||||||
|
this.getCondition().getAChild*().(VariableAccess).getTarget() = v and
|
||||||
|
(
|
||||||
|
exists(Assignment aexp |
|
||||||
|
this = aexp.getEnclosingStmt().getParentStmt*() and
|
||||||
|
(
|
||||||
|
aexp.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v
|
||||||
|
or
|
||||||
|
aexp.getLValue().(VariableAccess).getTarget() = v
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(CrementOperation crm |
|
||||||
|
this = crm.getEnclosingStmt().getParentStmt*() and
|
||||||
|
crm.getOperand().(VariableAccess).getTarget() = v
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from DangerousWhileLoop lp
|
||||||
|
where not lp.isUseThisVariable()
|
||||||
|
select lp.getDeclaration(), "A variable with this name is used in the $@ condition.", lp, "loop"
|
||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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.
|
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||||
*/
|
*/
|
||||||
private module LambdaFlow {
|
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)
|
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)
|
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 |
|
exists(int i |
|
||||||
viableParamNonLambda(call, i, p) and
|
viableParamNonLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
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 |
|
exists(int i |
|
||||||
viableParamLambda(call, i, p) and
|
viableParamLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
arg.argumentOf(call, i)
|
||||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||||
then compatibleTypes(t, getNodeType(node))
|
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
lambdaCall(lambdaCall, kind, node) and
|
lambdaCall(lambdaCall, kind, node) and
|
||||||
t = getNodeType(node) and
|
t = getNodeDataFlowType(node) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = false and
|
toJump = false and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
|||||||
toJump = true and
|
toJump = true and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
|
|
|
|
||||||
jumpStep(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
or
|
or
|
||||||
exists(boolean preservesValue |
|
exists(boolean preservesValue |
|
||||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow into a callable
|
// 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
|
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||||
(
|
(
|
||||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revLambdaFlowIn(
|
predicate revLambdaFlowIn(
|
||||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||||
DataFlowCallOption lastCall
|
DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module 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`.
|
* 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`.
|
* The instance parameter is considered to have index `-1`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
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)
|
p.isParameterOf(viableCallableExt(call), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +353,11 @@ private module Cached {
|
|||||||
* dispatch into account.
|
* dispatch into account.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
viableParam(call, i, p) and
|
viableParam(call, i, p) and
|
||||||
arg.argumentOf(call, i) 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`.
|
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||||
p = node and
|
p = node and
|
||||||
read = false
|
read = false
|
||||||
or
|
or
|
||||||
@@ -325,30 +408,30 @@ private module Cached {
|
|||||||
// read
|
// read
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
parameterValueFlowCand(p, mid, false) and
|
parameterValueFlowCand(p, mid, false) and
|
||||||
readStep(mid, _, node) and
|
read(mid, _, node) and
|
||||||
read = true
|
read = true
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no prior read
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, false) and
|
parameterValueFlowArgCand(p, arg, false) and
|
||||||
argumentValueFlowsThroughCand(arg, node, read)
|
argumentValueFlowsThroughCand(arg, node, read)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, read) and
|
parameterValueFlowArgCand(p, arg, read) and
|
||||||
argumentValueFlowsThroughCand(arg, node, false)
|
argumentValueFlowsThroughCand(arg, node, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||||
parameterValueFlowCand(p, arg, read)
|
parameterValueFlowCand(p, arg, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
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
|
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||||
* node.
|
* node.
|
||||||
*/
|
*/
|
||||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlowCand(p, ret, read) and
|
parameterValueFlowCand(p, ret, read) and
|
||||||
kind = ret.getKind()
|
kind = ret.getKind()
|
||||||
@@ -369,9 +452,9 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThroughCand0(
|
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)
|
parameterValueFlowReturnCand(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -382,14 +465,14 @@ private module Cached {
|
|||||||
*
|
*
|
||||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
* `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 |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate cand(ParameterNode p, Node n) {
|
predicate cand(ParamNode p, Node n) {
|
||||||
parameterValueFlowCand(p, n, _) and
|
parameterValueFlowCand(p, n, _) and
|
||||||
(
|
(
|
||||||
parameterValueFlowReturnCand(p, _, _)
|
parameterValueFlowReturnCand(p, _, _)
|
||||||
@@ -416,21 +499,21 @@ private module Cached {
|
|||||||
* If a read step was taken, then `read` captures the `Content`, the
|
* If a read step was taken, then `read` captures the `Content`, the
|
||||||
* container type, and the content type.
|
* 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
|
parameterValueFlow0(p, node, read) and
|
||||||
if node instanceof CastingNode
|
if node instanceof CastingNode
|
||||||
then
|
then
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||||
p = node and
|
p = node and
|
||||||
Cand::cand(p, _) and
|
Cand::cand(p, _) and
|
||||||
read = TReadStepTypesNone()
|
read = TReadStepTypesNone()
|
||||||
@@ -447,7 +530,7 @@ private module Cached {
|
|||||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||||
read.getContentType()) and
|
read.getContentType()) and
|
||||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||||
@@ -455,34 +538,32 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0_0(
|
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
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||||
argumentValueFlowsThrough(arg, read, node)
|
argumentValueFlowsThrough(arg, read, node)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, read) and
|
parameterValueFlowArg(p, arg, read) and
|
||||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArg(
|
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
|
||||||
) {
|
|
||||||
parameterValueFlow(p, arg, read) and
|
parameterValueFlow(p, arg, read) and
|
||||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThrough0(
|
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)
|
parameterValueFlowReturn(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -496,18 +577,18 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||||
exists(DataFlowCall call, ReturnKind kind |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
|
|
|
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +597,7 @@ private module Cached {
|
|||||||
* value-preserving steps and a single read step, not taking call
|
* value-preserving steps and a single read step, not taking call
|
||||||
* contexts into account, thus representing a getter-step.
|
* 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)
|
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +610,7 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
private predicate parameterValueFlowReturn(
|
private predicate parameterValueFlowReturn(
|
||||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||||
) {
|
) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlow(p, ret, read) and
|
parameterValueFlow(p, ret, read) and
|
||||||
@@ -553,7 +634,7 @@ private module Cached {
|
|||||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||||
mayBenefitFromCallContext(call, callable)
|
mayBenefitFromCallContext(call, callable)
|
||||||
or
|
or
|
||||||
callable = call.getEnclosingCallable() and
|
callEnclosingCallable(call, callable) and
|
||||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +692,7 @@ private module Cached {
|
|||||||
mayBenefitFromCallContextExt(call, _) and
|
mayBenefitFromCallContextExt(call, _) and
|
||||||
c = viableCallableExt(call) and
|
c = viableCallableExt(call) and
|
||||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) 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
|
ctxtgts < tgts
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -635,8 +716,7 @@ private module Cached {
|
|||||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
* 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.
|
* node `n`, in the same callable, using only value-preserving steps.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
|
||||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +724,9 @@ private module Cached {
|
|||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
storeStep(node1, c, node2) and
|
storeStep(node1, c, node2) and
|
||||||
readStep(_, c, _) and
|
read(_, c, _) and
|
||||||
contentType = getNodeType(node1) and
|
contentType = getNodeDataFlowType(node1) and
|
||||||
containerType = getNodeType(node2)
|
containerType = getNodeDataFlowType(node2)
|
||||||
or
|
or
|
||||||
exists(Node n1, Node n2 |
|
exists(Node n1, Node n2 |
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
@@ -654,12 +734,15 @@ private module Cached {
|
|||||||
|
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
or
|
or
|
||||||
readStep(n2, c, n1) and
|
read(n2, c, n1) and
|
||||||
contentType = getNodeType(n1) and
|
contentType = getNodeDataFlowType(n1) and
|
||||||
containerType = getNodeType(n2)
|
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
|
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||||
* `f`.
|
* `f`.
|
||||||
@@ -678,8 +761,9 @@ private module Cached {
|
|||||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate reverseStepThroughInputOutputAlias(
|
||||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||||
|
) {
|
||||||
exists(Node fromPre, Node toPre |
|
exists(Node fromPre, Node toPre |
|
||||||
fromPre = fromNode.getPreUpdateNode() and
|
fromPre = fromNode.getPreUpdateNode() and
|
||||||
toPre = toNode.getPreUpdateNode()
|
toPre = toNode.getPreUpdateNode()
|
||||||
@@ -688,14 +772,20 @@ private module Cached {
|
|||||||
// Does the language-specific simpleLocalFlowStep already model flow
|
// Does the language-specific simpleLocalFlowStep already model flow
|
||||||
// from function input to output?
|
// from function input to output?
|
||||||
fromPre = getAnOutNode(c, _) and
|
fromPre = getAnOutNode(c, _) and
|
||||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
toPre.(ArgNode).argumentOf(c, _) and
|
||||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
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
|
* Holds if the call context `call` either improves virtual dispatch in
|
||||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
* `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) {
|
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||||
reducedViableImplInCallContext(_, callable, call)
|
reducedViableImplInCallContext(_, callable, call)
|
||||||
or
|
or
|
||||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
@@ -726,12 +816,12 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
newtype TReturnKindExt =
|
||||||
TValueReturn(ReturnKind kind) or
|
TValueReturn(ReturnKind kind) or
|
||||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TBooleanOption =
|
newtype TBooleanOption =
|
||||||
@@ -761,23 +851,15 @@ private module Cached {
|
|||||||
* A `Node` at which a cast can occur such that the type should be checked.
|
* A `Node` at which a cast can occur such that the type should be checked.
|
||||||
*/
|
*/
|
||||||
class CastingNode extends Node {
|
class CastingNode extends Node {
|
||||||
CastingNode() {
|
CastingNode() { castingNode(this) }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate readStepWithTypes(
|
private predicate readStepWithTypes(
|
||||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||||
) {
|
) {
|
||||||
readStep(n1, c, n2) and
|
read(n1, c, n2) and
|
||||||
container = getNodeType(n1) and
|
container = getNodeDataFlowType(n1) and
|
||||||
content = getNodeType(n2)
|
content = getNodeDataFlowType(n2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TReadStepTypesOption =
|
private newtype TReadStepTypesOption =
|
||||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
|||||||
override string toString() { result = "CcSomeCall" }
|
override string toString() { result = "CcSomeCall" }
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
override predicate relevantFor(DataFlowCallable callable) {
|
||||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate matchesCall(DataFlowCall call) { any() }
|
override predicate matchesCall(DataFlowCall call) { any() }
|
||||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
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) {
|
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
|
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
|
* 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.
|
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||||
*/
|
*/
|
||||||
class ReturnNodeExt extends Node {
|
class ReturnNodeExt extends Node {
|
||||||
ReturnNodeExt() {
|
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||||
this instanceof ReturnNode or
|
|
||||||
parameterValueFlowsToPreUpdate(_, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the kind of this returned value. */
|
/** Gets the kind of this returned value. */
|
||||||
ReturnKindExt getKind() {
|
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||||
result = TValueReturn(this.(ReturnNode).getKind())
|
|
||||||
or
|
|
||||||
exists(ParameterNode p, int pos |
|
|
||||||
parameterValueFlowsToPreUpdate(p, this) and
|
|
||||||
p.isParameterOf(_, pos) and
|
|
||||||
result = TParamUpdate(pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
|||||||
* or a post-update node associated with a call argument.
|
* or a post-update node associated with a call argument.
|
||||||
*/
|
*/
|
||||||
class OutNodeExt extends Node {
|
class OutNodeExt extends Node {
|
||||||
OutNodeExt() {
|
OutNodeExt() { outNodeExt(this) }
|
||||||
this instanceof OutNode
|
|
||||||
or
|
|
||||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
|||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
/** Gets a node corresponding to data flow out of `call`. */
|
/** 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 {
|
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
|||||||
ReturnKind getKind() { result = kind }
|
ReturnKind getKind() { result = kind }
|
||||||
|
|
||||||
override string toString() { result = kind.toString() }
|
override string toString() { result = kind.toString() }
|
||||||
|
|
||||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
|
||||||
result = getAnOutNode(call, this.getKind())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
|||||||
int getPosition() { result = pos }
|
int getPosition() { result = pos }
|
||||||
|
|
||||||
override string toString() { result = "param update " + 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. */
|
/** A callable tagged with a relevant return kind. */
|
||||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||||
exists(Node n0 |
|
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
pragma[only_bind_into](n0) = n and
|
}
|
||||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
|
||||||
)
|
/** 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]
|
pragma[noinline]
|
||||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
|||||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||||
or
|
or
|
||||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||||
call0.getEnclosingCallable() = callable and
|
callEnclosingCallable(call0, callable) and
|
||||||
cc = TReturn(c0, call0) and
|
cc = TReturn(c0, call0) and
|
||||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||||
)
|
)
|
||||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
|||||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate read = readStep/3;
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
|||||||
|
|
||||||
TypedContent getHead() { this = TFrontHead(result) }
|
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 {
|
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||||
|
|||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||||
|
|||||||
@@ -526,7 +526,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
* This is the local flow predicate that's used as a building block in global
|
* This is the local flow predicate that's used as a building block in global
|
||||||
* data flow. It may have less flow than the `localFlowStep` predicate.
|
* data flow. It may have less flow than the `localFlowStep` predicate.
|
||||||
*/
|
*/
|
||||||
cached
|
|
||||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
// Expr -> Expr
|
// Expr -> Expr
|
||||||
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
|
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
|||||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||||
* different objects.
|
* different objects.
|
||||||
*/
|
*/
|
||||||
|
cached
|
||||||
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
// Taint can flow through expressions that alter the value but preserve
|
// Taint can flow through expressions that alter the value but preserve
|
||||||
// more than one bit of it _or_ expressions that follow data through
|
// more than one bit of it _or_ expressions that follow data through
|
||||||
|
|||||||
@@ -165,105 +165,132 @@ private predicate nodeIsBarrierEqualityCandidate(
|
|||||||
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate nodeIsBarrier(DataFlow::Node node) {
|
cached
|
||||||
exists(Variable checkedVar |
|
private module Cached {
|
||||||
readsVariable(node.asInstruction(), checkedVar) and
|
cached
|
||||||
hasUpperBoundsCheck(checkedVar)
|
predicate nodeIsBarrier(DataFlow::Node node) {
|
||||||
)
|
exists(Variable checkedVar |
|
||||||
or
|
readsVariable(node.asInstruction(), checkedVar) and
|
||||||
exists(Variable checkedVar, Operand access |
|
hasUpperBoundsCheck(checkedVar)
|
||||||
/*
|
)
|
||||||
* This node is guarded by a condition that forces the accessed variable
|
|
||||||
* to equal something else. For example:
|
|
||||||
* ```
|
|
||||||
* x = taintsource()
|
|
||||||
* if (x == 10) {
|
|
||||||
* taintsink(x); // not considered tainted
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
|
|
||||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
|
|
||||||
readsVariable(access.getDef(), checkedVar)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private predicate nodeIsBarrierIn(DataFlow::Node node) {
|
|
||||||
// don't use dataflow into taint sources, as this leads to duplicate results.
|
|
||||||
exists(Expr source | isUserInput(source, _) |
|
|
||||||
node = DataFlow::exprNode(source)
|
|
||||||
or
|
or
|
||||||
// This case goes together with the similar (but not identical) rule in
|
exists(Variable checkedVar, Operand access |
|
||||||
// `getNodeForSource`.
|
/*
|
||||||
node = DataFlow::definitionByReferenceNodeFromArgument(source)
|
* This node is guarded by a condition that forces the accessed variable
|
||||||
)
|
* to equal something else. For example:
|
||||||
or
|
* ```
|
||||||
// don't use dataflow into binary instructions if both operands are unpredictable
|
* x = taintsource()
|
||||||
exists(BinaryInstruction iTo |
|
* if (x == 10) {
|
||||||
iTo = node.asInstruction() and
|
* taintsink(x); // not considered tainted
|
||||||
not predictableInstruction(iTo.getLeft()) and
|
* }
|
||||||
not predictableInstruction(iTo.getRight()) and
|
* ```
|
||||||
// propagate taint from either the pointer or the offset, regardless of predictability
|
*/
|
||||||
not iTo instanceof PointerArithmeticInstruction
|
|
||||||
)
|
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
|
||||||
or
|
readsVariable(access.getDef(), checkedVar)
|
||||||
// don't use dataflow through calls to pure functions if two or more operands
|
)
|
||||||
// are unpredictable
|
}
|
||||||
exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
|
|
||||||
iTo = node.asInstruction() and
|
cached
|
||||||
isPureFunction(iTo.getStaticCallTarget().getName()) and
|
predicate nodeIsBarrierIn(DataFlow::Node node) {
|
||||||
iFrom1 = iTo.getAnArgument() and
|
// don't use dataflow into taint sources, as this leads to duplicate results.
|
||||||
iFrom2 = iTo.getAnArgument() and
|
exists(Expr source | isUserInput(source, _) |
|
||||||
not predictableInstruction(iFrom1) and
|
node = DataFlow::exprNode(source)
|
||||||
not predictableInstruction(iFrom2) and
|
or
|
||||||
iFrom1 != iFrom2
|
// This case goes together with the similar (but not identical) rule in
|
||||||
)
|
// `getNodeForSource`.
|
||||||
|
node = DataFlow::definitionByReferenceNodeFromArgument(source)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// don't use dataflow into binary instructions if both operands are unpredictable
|
||||||
|
exists(BinaryInstruction iTo |
|
||||||
|
iTo = node.asInstruction() and
|
||||||
|
not predictableInstruction(iTo.getLeft()) and
|
||||||
|
not predictableInstruction(iTo.getRight()) and
|
||||||
|
// propagate taint from either the pointer or the offset, regardless of predictability
|
||||||
|
not iTo instanceof PointerArithmeticInstruction
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// don't use dataflow through calls to pure functions if two or more operands
|
||||||
|
// are unpredictable
|
||||||
|
exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
|
||||||
|
iTo = node.asInstruction() and
|
||||||
|
isPureFunction(iTo.getStaticCallTarget().getName()) and
|
||||||
|
iFrom1 = iTo.getAnArgument() and
|
||||||
|
iFrom2 = iTo.getAnArgument() and
|
||||||
|
not predictableInstruction(iFrom1) and
|
||||||
|
not predictableInstruction(iFrom2) and
|
||||||
|
iFrom1 != iFrom2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
cached
|
||||||
|
Element adjustedSink(DataFlow::Node sink) {
|
||||||
|
// TODO: is it more appropriate to use asConvertedExpr here and avoid
|
||||||
|
// `getConversion*`? Or will that cause us to miss some cases where there's
|
||||||
|
// flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
|
||||||
|
// pretend there was flow to the converted `Expr` for the sake of
|
||||||
|
// compatibility.
|
||||||
|
sink.asExpr().getConversion*() = result
|
||||||
|
or
|
||||||
|
// For compatibility, send flow from arguments to parameters, even for
|
||||||
|
// functions with no body.
|
||||||
|
exists(FunctionCall call, int i |
|
||||||
|
sink.asExpr() = call.getArgument(i) and
|
||||||
|
result = resolveCall(call).getParameter(i)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// For compatibility, send flow into a `Variable` if there is flow to any
|
||||||
|
// Load or Store of that variable.
|
||||||
|
exists(CopyInstruction copy |
|
||||||
|
copy.getSourceValue() = sink.asInstruction() and
|
||||||
|
(
|
||||||
|
readsVariable(copy, result) or
|
||||||
|
writesVariable(copy, result)
|
||||||
|
) and
|
||||||
|
not hasUpperBoundsCheck(result)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// For compatibility, send flow into a `NotExpr` even if it's part of a
|
||||||
|
// short-circuiting condition and thus might get skipped.
|
||||||
|
result.(NotExpr).getOperand() = sink.asExpr()
|
||||||
|
or
|
||||||
|
// Taint postfix and prefix crement operations when their operand is tainted.
|
||||||
|
result.(CrementOperation).getAnOperand() = sink.asExpr()
|
||||||
|
or
|
||||||
|
// Taint `e1 += e2`, `e &= e2` and friends when `e1` or `e2` is tainted.
|
||||||
|
result.(AssignOperation).getAnOperand() = sink.asExpr()
|
||||||
|
or
|
||||||
|
result =
|
||||||
|
sink.asOperand()
|
||||||
|
.(SideEffectOperand)
|
||||||
|
.getUse()
|
||||||
|
.(ReadSideEffectInstruction)
|
||||||
|
.getArgumentDef()
|
||||||
|
.getUnconvertedResultExpression()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step to return value of a modeled function when an input taints the
|
||||||
|
* dereference of the return value.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate additionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
|
exists(CallInstruction call, Function func, FunctionInput modelIn, FunctionOutput modelOut |
|
||||||
|
n1.asOperand() = callInput(call, modelIn) and
|
||||||
|
(
|
||||||
|
func.(TaintFunction).hasTaintFlow(modelIn, modelOut)
|
||||||
|
or
|
||||||
|
func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
|
||||||
|
) and
|
||||||
|
call.getStaticCallTarget() = func and
|
||||||
|
modelOut.isReturnValueDeref() and
|
||||||
|
call = n2.asInstruction()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element adjustedSink(DataFlow::Node sink) {
|
private import Cached
|
||||||
// TODO: is it more appropriate to use asConvertedExpr here and avoid
|
|
||||||
// `getConversion*`? Or will that cause us to miss some cases where there's
|
|
||||||
// flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
|
|
||||||
// pretend there was flow to the converted `Expr` for the sake of
|
|
||||||
// compatibility.
|
|
||||||
sink.asExpr().getConversion*() = result
|
|
||||||
or
|
|
||||||
// For compatibility, send flow from arguments to parameters, even for
|
|
||||||
// functions with no body.
|
|
||||||
exists(FunctionCall call, int i |
|
|
||||||
sink.asExpr() = call.getArgument(i) and
|
|
||||||
result = resolveCall(call).getParameter(i)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// For compatibility, send flow into a `Variable` if there is flow to any
|
|
||||||
// Load or Store of that variable.
|
|
||||||
exists(CopyInstruction copy |
|
|
||||||
copy.getSourceValue() = sink.asInstruction() and
|
|
||||||
(
|
|
||||||
readsVariable(copy, result) or
|
|
||||||
writesVariable(copy, result)
|
|
||||||
) and
|
|
||||||
not hasUpperBoundsCheck(result)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// For compatibility, send flow into a `NotExpr` even if it's part of a
|
|
||||||
// short-circuiting condition and thus might get skipped.
|
|
||||||
result.(NotExpr).getOperand() = sink.asExpr()
|
|
||||||
or
|
|
||||||
// Taint postfix and prefix crement operations when their operand is tainted.
|
|
||||||
result.(CrementOperation).getAnOperand() = sink.asExpr()
|
|
||||||
or
|
|
||||||
// Taint `e1 += e2`, `e &= e2` and friends when `e1` or `e2` is tainted.
|
|
||||||
result.(AssignOperation).getAnOperand() = sink.asExpr()
|
|
||||||
or
|
|
||||||
result =
|
|
||||||
sink.asOperand()
|
|
||||||
.(SideEffectOperand)
|
|
||||||
.getUse()
|
|
||||||
.(ReadSideEffectInstruction)
|
|
||||||
.getArgumentDef()
|
|
||||||
.getUnconvertedResultExpression()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `tainted` may contain taint from `source`.
|
* Holds if `tainted` may contain taint from `source`.
|
||||||
@@ -402,19 +429,7 @@ module TaintedWithPath {
|
|||||||
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
|
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Step to return value of a modeled function when an input taints the
|
additionalTaintStep(n1, n2)
|
||||||
// dereference of the return value
|
|
||||||
exists(CallInstruction call, Function func, FunctionInput modelIn, FunctionOutput modelOut |
|
|
||||||
n1.asOperand() = callInput(call, modelIn) and
|
|
||||||
(
|
|
||||||
func.(TaintFunction).hasTaintFlow(modelIn, modelOut)
|
|
||||||
or
|
|
||||||
func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
|
|
||||||
) and
|
|
||||||
call.getStaticCallTarget() = func and
|
|
||||||
modelOut.isReturnValueDeref() and
|
|
||||||
call = n2.asInstruction()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
override predicate isSanitizer(DataFlow::Node node) {
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ private import cpp
|
|||||||
private import semmle.code.cpp.ir.IR
|
private import semmle.code.cpp.ir.IR
|
||||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||||
|
private import DataFlowImplCommon as DataFlowImplCommon
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a function that might be called by `call`.
|
* Gets a function that might be called by `call`.
|
||||||
*/
|
*/
|
||||||
|
cached
|
||||||
Function viableCallable(CallInstruction call) {
|
Function viableCallable(CallInstruction call) {
|
||||||
|
DataFlowImplCommon::forceCachingInSameStage() and
|
||||||
result = call.getStaticCallTarget()
|
result = call.getStaticCallTarget()
|
||||||
or
|
or
|
||||||
// If the target of the call does not have a body in the snapshot, it might
|
// If the target of the call does not have a body in the snapshot, it might
|
||||||
@@ -43,7 +46,6 @@ private module VirtualDispatch {
|
|||||||
abstract DataFlow::Node getDispatchValue();
|
abstract DataFlow::Node getDispatchValue();
|
||||||
|
|
||||||
/** Gets a candidate target for this call. */
|
/** Gets a candidate target for this call. */
|
||||||
cached
|
|
||||||
abstract Function resolve();
|
abstract Function resolve();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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.
|
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||||
*/
|
*/
|
||||||
private module LambdaFlow {
|
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)
|
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)
|
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 |
|
exists(int i |
|
||||||
viableParamNonLambda(call, i, p) and
|
viableParamNonLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
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 |
|
exists(int i |
|
||||||
viableParamLambda(call, i, p) and
|
viableParamLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
arg.argumentOf(call, i)
|
||||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||||
then compatibleTypes(t, getNodeType(node))
|
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
lambdaCall(lambdaCall, kind, node) and
|
lambdaCall(lambdaCall, kind, node) and
|
||||||
t = getNodeType(node) and
|
t = getNodeDataFlowType(node) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = false and
|
toJump = false and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
|||||||
toJump = true and
|
toJump = true and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
|
|
|
|
||||||
jumpStep(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
or
|
or
|
||||||
exists(boolean preservesValue |
|
exists(boolean preservesValue |
|
||||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow into a callable
|
// 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
|
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||||
(
|
(
|
||||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revLambdaFlowIn(
|
predicate revLambdaFlowIn(
|
||||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||||
DataFlowCallOption lastCall
|
DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module 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`.
|
* 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`.
|
* The instance parameter is considered to have index `-1`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
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)
|
p.isParameterOf(viableCallableExt(call), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +353,11 @@ private module Cached {
|
|||||||
* dispatch into account.
|
* dispatch into account.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
viableParam(call, i, p) and
|
viableParam(call, i, p) and
|
||||||
arg.argumentOf(call, i) 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`.
|
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||||
p = node and
|
p = node and
|
||||||
read = false
|
read = false
|
||||||
or
|
or
|
||||||
@@ -325,30 +408,30 @@ private module Cached {
|
|||||||
// read
|
// read
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
parameterValueFlowCand(p, mid, false) and
|
parameterValueFlowCand(p, mid, false) and
|
||||||
readStep(mid, _, node) and
|
read(mid, _, node) and
|
||||||
read = true
|
read = true
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no prior read
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, false) and
|
parameterValueFlowArgCand(p, arg, false) and
|
||||||
argumentValueFlowsThroughCand(arg, node, read)
|
argumentValueFlowsThroughCand(arg, node, read)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, read) and
|
parameterValueFlowArgCand(p, arg, read) and
|
||||||
argumentValueFlowsThroughCand(arg, node, false)
|
argumentValueFlowsThroughCand(arg, node, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||||
parameterValueFlowCand(p, arg, read)
|
parameterValueFlowCand(p, arg, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
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
|
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||||
* node.
|
* node.
|
||||||
*/
|
*/
|
||||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlowCand(p, ret, read) and
|
parameterValueFlowCand(p, ret, read) and
|
||||||
kind = ret.getKind()
|
kind = ret.getKind()
|
||||||
@@ -369,9 +452,9 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThroughCand0(
|
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)
|
parameterValueFlowReturnCand(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -382,14 +465,14 @@ private module Cached {
|
|||||||
*
|
*
|
||||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
* `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 |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate cand(ParameterNode p, Node n) {
|
predicate cand(ParamNode p, Node n) {
|
||||||
parameterValueFlowCand(p, n, _) and
|
parameterValueFlowCand(p, n, _) and
|
||||||
(
|
(
|
||||||
parameterValueFlowReturnCand(p, _, _)
|
parameterValueFlowReturnCand(p, _, _)
|
||||||
@@ -416,21 +499,21 @@ private module Cached {
|
|||||||
* If a read step was taken, then `read` captures the `Content`, the
|
* If a read step was taken, then `read` captures the `Content`, the
|
||||||
* container type, and the content type.
|
* 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
|
parameterValueFlow0(p, node, read) and
|
||||||
if node instanceof CastingNode
|
if node instanceof CastingNode
|
||||||
then
|
then
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||||
p = node and
|
p = node and
|
||||||
Cand::cand(p, _) and
|
Cand::cand(p, _) and
|
||||||
read = TReadStepTypesNone()
|
read = TReadStepTypesNone()
|
||||||
@@ -447,7 +530,7 @@ private module Cached {
|
|||||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||||
read.getContentType()) and
|
read.getContentType()) and
|
||||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||||
@@ -455,34 +538,32 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0_0(
|
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
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||||
argumentValueFlowsThrough(arg, read, node)
|
argumentValueFlowsThrough(arg, read, node)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, read) and
|
parameterValueFlowArg(p, arg, read) and
|
||||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArg(
|
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
|
||||||
) {
|
|
||||||
parameterValueFlow(p, arg, read) and
|
parameterValueFlow(p, arg, read) and
|
||||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThrough0(
|
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)
|
parameterValueFlowReturn(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -496,18 +577,18 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||||
exists(DataFlowCall call, ReturnKind kind |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
|
|
|
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +597,7 @@ private module Cached {
|
|||||||
* value-preserving steps and a single read step, not taking call
|
* value-preserving steps and a single read step, not taking call
|
||||||
* contexts into account, thus representing a getter-step.
|
* 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)
|
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +610,7 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
private predicate parameterValueFlowReturn(
|
private predicate parameterValueFlowReturn(
|
||||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||||
) {
|
) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlow(p, ret, read) and
|
parameterValueFlow(p, ret, read) and
|
||||||
@@ -553,7 +634,7 @@ private module Cached {
|
|||||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||||
mayBenefitFromCallContext(call, callable)
|
mayBenefitFromCallContext(call, callable)
|
||||||
or
|
or
|
||||||
callable = call.getEnclosingCallable() and
|
callEnclosingCallable(call, callable) and
|
||||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +692,7 @@ private module Cached {
|
|||||||
mayBenefitFromCallContextExt(call, _) and
|
mayBenefitFromCallContextExt(call, _) and
|
||||||
c = viableCallableExt(call) and
|
c = viableCallableExt(call) and
|
||||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) 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
|
ctxtgts < tgts
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -635,8 +716,7 @@ private module Cached {
|
|||||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
* 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.
|
* node `n`, in the same callable, using only value-preserving steps.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
|
||||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +724,9 @@ private module Cached {
|
|||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
storeStep(node1, c, node2) and
|
storeStep(node1, c, node2) and
|
||||||
readStep(_, c, _) and
|
read(_, c, _) and
|
||||||
contentType = getNodeType(node1) and
|
contentType = getNodeDataFlowType(node1) and
|
||||||
containerType = getNodeType(node2)
|
containerType = getNodeDataFlowType(node2)
|
||||||
or
|
or
|
||||||
exists(Node n1, Node n2 |
|
exists(Node n1, Node n2 |
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
@@ -654,12 +734,15 @@ private module Cached {
|
|||||||
|
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
or
|
or
|
||||||
readStep(n2, c, n1) and
|
read(n2, c, n1) and
|
||||||
contentType = getNodeType(n1) and
|
contentType = getNodeDataFlowType(n1) and
|
||||||
containerType = getNodeType(n2)
|
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
|
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||||
* `f`.
|
* `f`.
|
||||||
@@ -678,8 +761,9 @@ private module Cached {
|
|||||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate reverseStepThroughInputOutputAlias(
|
||||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||||
|
) {
|
||||||
exists(Node fromPre, Node toPre |
|
exists(Node fromPre, Node toPre |
|
||||||
fromPre = fromNode.getPreUpdateNode() and
|
fromPre = fromNode.getPreUpdateNode() and
|
||||||
toPre = toNode.getPreUpdateNode()
|
toPre = toNode.getPreUpdateNode()
|
||||||
@@ -688,14 +772,20 @@ private module Cached {
|
|||||||
// Does the language-specific simpleLocalFlowStep already model flow
|
// Does the language-specific simpleLocalFlowStep already model flow
|
||||||
// from function input to output?
|
// from function input to output?
|
||||||
fromPre = getAnOutNode(c, _) and
|
fromPre = getAnOutNode(c, _) and
|
||||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
toPre.(ArgNode).argumentOf(c, _) and
|
||||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
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
|
* Holds if the call context `call` either improves virtual dispatch in
|
||||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
* `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) {
|
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||||
reducedViableImplInCallContext(_, callable, call)
|
reducedViableImplInCallContext(_, callable, call)
|
||||||
or
|
or
|
||||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
@@ -726,12 +816,12 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
newtype TReturnKindExt =
|
||||||
TValueReturn(ReturnKind kind) or
|
TValueReturn(ReturnKind kind) or
|
||||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TBooleanOption =
|
newtype TBooleanOption =
|
||||||
@@ -761,23 +851,15 @@ private module Cached {
|
|||||||
* A `Node` at which a cast can occur such that the type should be checked.
|
* A `Node` at which a cast can occur such that the type should be checked.
|
||||||
*/
|
*/
|
||||||
class CastingNode extends Node {
|
class CastingNode extends Node {
|
||||||
CastingNode() {
|
CastingNode() { castingNode(this) }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate readStepWithTypes(
|
private predicate readStepWithTypes(
|
||||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||||
) {
|
) {
|
||||||
readStep(n1, c, n2) and
|
read(n1, c, n2) and
|
||||||
container = getNodeType(n1) and
|
container = getNodeDataFlowType(n1) and
|
||||||
content = getNodeType(n2)
|
content = getNodeDataFlowType(n2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TReadStepTypesOption =
|
private newtype TReadStepTypesOption =
|
||||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
|||||||
override string toString() { result = "CcSomeCall" }
|
override string toString() { result = "CcSomeCall" }
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
override predicate relevantFor(DataFlowCallable callable) {
|
||||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate matchesCall(DataFlowCall call) { any() }
|
override predicate matchesCall(DataFlowCall call) { any() }
|
||||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
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) {
|
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
|
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
|
* 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.
|
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||||
*/
|
*/
|
||||||
class ReturnNodeExt extends Node {
|
class ReturnNodeExt extends Node {
|
||||||
ReturnNodeExt() {
|
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||||
this instanceof ReturnNode or
|
|
||||||
parameterValueFlowsToPreUpdate(_, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the kind of this returned value. */
|
/** Gets the kind of this returned value. */
|
||||||
ReturnKindExt getKind() {
|
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||||
result = TValueReturn(this.(ReturnNode).getKind())
|
|
||||||
or
|
|
||||||
exists(ParameterNode p, int pos |
|
|
||||||
parameterValueFlowsToPreUpdate(p, this) and
|
|
||||||
p.isParameterOf(_, pos) and
|
|
||||||
result = TParamUpdate(pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
|||||||
* or a post-update node associated with a call argument.
|
* or a post-update node associated with a call argument.
|
||||||
*/
|
*/
|
||||||
class OutNodeExt extends Node {
|
class OutNodeExt extends Node {
|
||||||
OutNodeExt() {
|
OutNodeExt() { outNodeExt(this) }
|
||||||
this instanceof OutNode
|
|
||||||
or
|
|
||||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
|||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
/** Gets a node corresponding to data flow out of `call`. */
|
/** 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 {
|
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
|||||||
ReturnKind getKind() { result = kind }
|
ReturnKind getKind() { result = kind }
|
||||||
|
|
||||||
override string toString() { result = kind.toString() }
|
override string toString() { result = kind.toString() }
|
||||||
|
|
||||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
|
||||||
result = getAnOutNode(call, this.getKind())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
|||||||
int getPosition() { result = pos }
|
int getPosition() { result = pos }
|
||||||
|
|
||||||
override string toString() { result = "param update " + 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. */
|
/** A callable tagged with a relevant return kind. */
|
||||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||||
exists(Node n0 |
|
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
pragma[only_bind_into](n0) = n and
|
}
|
||||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
|
||||||
)
|
/** 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]
|
pragma[noinline]
|
||||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
|||||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||||
or
|
or
|
||||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||||
call0.getEnclosingCallable() = callable and
|
callEnclosingCallable(call0, callable) and
|
||||||
cc = TReturn(c0, call0) and
|
cc = TReturn(c0, call0) and
|
||||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||||
)
|
)
|
||||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
|||||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate read = readStep/3;
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
|||||||
|
|
||||||
TypedContent getHead() { this = TFrontHead(result) }
|
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 {
|
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||||
|
|||||||
@@ -12,10 +12,20 @@ private import semmle.code.cpp.controlflow.IRGuards
|
|||||||
private import semmle.code.cpp.models.interfaces.DataFlow
|
private import semmle.code.cpp.models.interfaces.DataFlow
|
||||||
|
|
||||||
cached
|
cached
|
||||||
private newtype TIRDataFlowNode =
|
private module Cached {
|
||||||
TInstructionNode(Instruction i) or
|
cached
|
||||||
TOperandNode(Operand op) or
|
newtype TIRDataFlowNode =
|
||||||
TVariableNode(Variable var)
|
TInstructionNode(Instruction i) or
|
||||||
|
TOperandNode(Operand op) or
|
||||||
|
TVariableNode(Variable var)
|
||||||
|
|
||||||
|
cached
|
||||||
|
predicate localFlowStepCached(Node nodeFrom, Node nodeTo) {
|
||||||
|
simpleLocalFlowStep(nodeFrom, nodeTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private import Cached
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in a data flow graph.
|
* A node in a data flow graph.
|
||||||
@@ -590,7 +600,7 @@ Node uninitializedNode(LocalVariable v) { none() }
|
|||||||
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
|
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
|
||||||
* (intra-procedural) step.
|
* (intra-procedural) step.
|
||||||
*/
|
*/
|
||||||
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
|
predicate localFlowStep = localFlowStepCached/2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL: do not use.
|
* INTERNAL: do not use.
|
||||||
@@ -598,7 +608,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
|
|||||||
* This is the local flow predicate that's used as a building block in global
|
* This is the local flow predicate that's used as a building block in global
|
||||||
* data flow. It may have less flow than the `localFlowStep` predicate.
|
* data flow. It may have less flow than the `localFlowStep` predicate.
|
||||||
*/
|
*/
|
||||||
cached
|
|
||||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
// Operand -> Instruction flow
|
// Operand -> Instruction flow
|
||||||
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
|
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
|||||||
* Holds if the value of `use` is guarded using `abs`.
|
* Holds if the value of `use` is guarded using `abs`.
|
||||||
*/
|
*/
|
||||||
predicate guardedAbs(Operation e, Expr use) {
|
predicate guardedAbs(Operation e, Expr use) {
|
||||||
exists(FunctionCall fc | fc.getTarget().getName() = "abs" |
|
exists(FunctionCall fc | fc.getTarget().getName() = ["abs", "labs", "llabs", "imaxabs"] |
|
||||||
fc.getArgument(0).getAChild*() = use and
|
fc.getArgument(0).getAChild*() = use and
|
||||||
guardedLesser(e, fc)
|
guardedLesser(e, fc)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
| test.c:14:9:14:16 | intIndex | A variable with this name is used in the $@ condition. | test.c:11:3:16:3 | while (...) ... | loop |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
void workFunction_0(char *s) {
|
||||||
|
int intIndex = 10;
|
||||||
|
int intGuard;
|
||||||
|
char buf[80];
|
||||||
|
while(intIndex > 2) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
intIndex--;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
while(intIndex > 2)
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
int intIndex; // BAD
|
||||||
|
intIndex--;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
intGuard = 20;
|
||||||
|
while(intIndex < intGuard--) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
int intIndex;
|
||||||
|
intIndex--;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
intGuard = 20;
|
||||||
|
while(intIndex < intGuard) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
int intIndex;
|
||||||
|
intIndex++;
|
||||||
|
intGuard--;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
intGuard = 20;
|
||||||
|
while(intIndex < intGuard) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
int intIndex;
|
||||||
|
intIndex--;
|
||||||
|
intGuard -= 4;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
while(intIndex > 2) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
intIndex -= 2;
|
||||||
|
int intIndex;
|
||||||
|
intIndex--;
|
||||||
|
}
|
||||||
|
intIndex = 10;
|
||||||
|
while(intIndex > 2) // GOOD
|
||||||
|
{
|
||||||
|
buf[intIndex] = 1;
|
||||||
|
--intIndex;
|
||||||
|
int intIndex;
|
||||||
|
intIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,3 +18,25 @@ void useTaintedInt()
|
|||||||
y = getTaintedInt();
|
y = getTaintedInt();
|
||||||
y = y * 1024; // BAD: arithmetic on a tainted value
|
y = y * 1024; // BAD: arithmetic on a tainted value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef long long int intmax_t;
|
||||||
|
|
||||||
|
intmax_t imaxabs(intmax_t j);
|
||||||
|
|
||||||
|
void useTaintedIntWithGuard() {
|
||||||
|
int tainted = getTaintedInt();
|
||||||
|
|
||||||
|
if(imaxabs(tainted) <= 100) {
|
||||||
|
int product = tainted * tainted; // GOOD: can't underflow/overflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INTMAX_MIN (-0x7fffffffffffffff - 1)
|
||||||
|
|
||||||
|
void useTaintedIntWithGuardIntMaxMin() {
|
||||||
|
intmax_t tainted = getTaintedInt();
|
||||||
|
|
||||||
|
if(imaxabs(tainted) <= INTMAX_MIN) {
|
||||||
|
int product = tainted * tainted; // BAD: imaxabs(INTMAX_MIN) == INTMAX_MIN [NOT DETECTED]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -170,7 +170,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
|
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
|
||||||
int childIndex, Extraction.Entities.Location location)
|
int childIndex, Extraction.Entities.Location location)
|
||||||
{
|
{
|
||||||
if (!parameter.HasExplicitDefaultValue)
|
if (!parameter.HasExplicitDefaultValue ||
|
||||||
|
parameter.Type is IErrorTypeSymbol)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
|
|
||||||
public override void WriteId(EscapingTextWriter trapFile)
|
public override void WriteId(EscapingTextWriter trapFile)
|
||||||
{
|
{
|
||||||
Symbol.BuildTypeId(Context, trapFile, Symbol);
|
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
|
||||||
trapFile.Write(";functionpointertype");
|
trapFile.Write(";functionpointertype");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
|
|
||||||
public override void WriteId(EscapingTextWriter trapFile)
|
public override void WriteId(EscapingTextWriter trapFile)
|
||||||
{
|
{
|
||||||
Symbol.BuildTypeId(Context, trapFile, Symbol);
|
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
|
||||||
trapFile.Write(";tuple");
|
trapFile.Write(";tuple");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,22 +81,45 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
|
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
|
||||||
trapFile.WriteLine("\")");
|
trapFile.WriteLine("\")");
|
||||||
|
|
||||||
|
var baseTypes = GetBaseTypeDeclarations();
|
||||||
|
|
||||||
// Visit base types
|
// Visit base types
|
||||||
var baseTypes = new List<Type>();
|
|
||||||
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
||||||
{
|
{
|
||||||
var baseKey = Create(Context, @base);
|
var bts = GetBaseTypeDeclarations(baseTypes, @base);
|
||||||
trapFile.extend(this, baseKey.TypeRef);
|
|
||||||
if (Symbol.TypeKind != TypeKind.Struct)
|
Context.PopulateLater(() =>
|
||||||
baseTypes.Add(baseKey);
|
{
|
||||||
|
var baseKey = Create(Context, @base);
|
||||||
|
trapFile.extend(this, baseKey.TypeRef);
|
||||||
|
|
||||||
|
if (Symbol.TypeKind != TypeKind.Struct)
|
||||||
|
{
|
||||||
|
foreach (var bt in bts)
|
||||||
|
{
|
||||||
|
TypeMention.Create(Context, bt.Type, this, baseKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Visit implemented interfaces
|
||||||
if (!(base.Symbol is IArrayTypeSymbol))
|
if (!(base.Symbol is IArrayTypeSymbol))
|
||||||
{
|
{
|
||||||
foreach (var t in base.Symbol.Interfaces.Select(i => Create(Context, i)))
|
foreach (var i in base.Symbol.Interfaces)
|
||||||
{
|
{
|
||||||
trapFile.implement(this, t.TypeRef);
|
var bts = GetBaseTypeDeclarations(baseTypes, i);
|
||||||
baseTypes.Add(t);
|
|
||||||
|
Context.PopulateLater(() =>
|
||||||
|
{
|
||||||
|
var interfaceKey = Create(Context, i);
|
||||||
|
trapFile.implement(this, interfaceKey.TypeRef);
|
||||||
|
|
||||||
|
foreach (var bt in bts)
|
||||||
|
{
|
||||||
|
TypeMention.Create(Context, bt.Type, this, interfaceKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,23 +168,30 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
Modifier.ExtractModifiers(Context, trapFile, this, Symbol);
|
Modifier.ExtractModifiers(Context, trapFile, this, Symbol);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsSourceDeclaration && Symbol.FromSource())
|
private IEnumerable<BaseTypeSyntax> GetBaseTypeDeclarations()
|
||||||
|
{
|
||||||
|
if (!IsSourceDeclaration || !Symbol.FromSource())
|
||||||
{
|
{
|
||||||
var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
|
return Enumerable.Empty<BaseTypeSyntax>();
|
||||||
|
|
||||||
var baseLists = declSyntaxReferences.OfType<ClassDeclarationSyntax>().Select(c => c.BaseList);
|
|
||||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<InterfaceDeclarationSyntax>().Select(c => c.BaseList));
|
|
||||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<StructDeclarationSyntax>().Select(c => c.BaseList));
|
|
||||||
|
|
||||||
baseLists
|
|
||||||
.Where(bl => bl is not null)
|
|
||||||
.SelectMany(bl => bl!.Types)
|
|
||||||
.Zip(
|
|
||||||
baseTypes.Where(bt => bt.Symbol.SpecialType != SpecialType.System_Object),
|
|
||||||
(s, t) => TypeMention.Create(Context, s.Type, this, t))
|
|
||||||
.Enumerate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
|
||||||
|
|
||||||
|
var baseLists = declSyntaxReferences.OfType<ClassDeclarationSyntax>().Select(c => c.BaseList);
|
||||||
|
baseLists = baseLists.Concat(declSyntaxReferences.OfType<InterfaceDeclarationSyntax>().Select(c => c.BaseList));
|
||||||
|
baseLists = baseLists.Concat(declSyntaxReferences.OfType<StructDeclarationSyntax>().Select(c => c.BaseList));
|
||||||
|
|
||||||
|
return baseLists
|
||||||
|
.Where(bl => bl is not null)
|
||||||
|
.SelectMany(bl => bl!.Types)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<BaseTypeSyntax> GetBaseTypeDeclarations(IEnumerable<BaseTypeSyntax> baseTypes, INamedTypeSymbol type)
|
||||||
|
{
|
||||||
|
return baseTypes.Where(bt => SymbolEqualityComparer.Default.Equals(Context.GetModel(bt).GetTypeInfo(bt.Type).Type, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSymbol invokeMethod, Action<Type> storeReturnType)
|
private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSymbol invokeMethod, Action<Type> storeReturnType)
|
||||||
|
|||||||
@@ -121,8 +121,6 @@ namespace Semmle.Extraction.CSharp
|
|||||||
named = named.TupleUnderlyingType;
|
named = named.TupleUnderlyingType;
|
||||||
if (IdDependsOnImpl(named.ContainingType))
|
if (IdDependsOnImpl(named.ContainingType))
|
||||||
return true;
|
return true;
|
||||||
if (IdDependsOnImpl(named.GetNonObjectBaseType(cx)))
|
|
||||||
return true;
|
|
||||||
if (IdDependsOnImpl(named.ConstructedFrom))
|
if (IdDependsOnImpl(named.ConstructedFrom))
|
||||||
return true;
|
return true;
|
||||||
return named.TypeArguments.Any(IdDependsOnImpl);
|
return named.TypeArguments.Any(IdDependsOnImpl);
|
||||||
@@ -160,10 +158,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
/// <param name="trapFile">The trap builder used to store the result.</param>
|
/// <param name="trapFile">The trap builder used to store the result.</param>
|
||||||
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
|
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
|
||||||
/// <param name="constructUnderlyingTupleType">Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.</param>
|
/// <param name="constructUnderlyingTupleType">Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.</param>
|
||||||
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
|
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, true, constructUnderlyingTupleType);
|
|
||||||
|
|
||||||
private static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
|
|
||||||
{
|
{
|
||||||
using (cx.StackGuard)
|
using (cx.StackGuard)
|
||||||
{
|
{
|
||||||
@@ -171,7 +166,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
{
|
{
|
||||||
case TypeKind.Array:
|
case TypeKind.Array:
|
||||||
var array = (IArrayTypeSymbol)type;
|
var array = (IArrayTypeSymbol)type;
|
||||||
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
array.BuildArraySuffix(trapFile);
|
array.BuildArraySuffix(trapFile);
|
||||||
return;
|
return;
|
||||||
case TypeKind.Class:
|
case TypeKind.Class:
|
||||||
@@ -181,16 +176,16 @@ namespace Semmle.Extraction.CSharp
|
|||||||
case TypeKind.Delegate:
|
case TypeKind.Delegate:
|
||||||
case TypeKind.Error:
|
case TypeKind.Error:
|
||||||
var named = (INamedTypeSymbol)type;
|
var named = (INamedTypeSymbol)type;
|
||||||
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||||
return;
|
return;
|
||||||
case TypeKind.Pointer:
|
case TypeKind.Pointer:
|
||||||
var ptr = (IPointerTypeSymbol)type;
|
var ptr = (IPointerTypeSymbol)type;
|
||||||
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
trapFile.Write('*');
|
trapFile.Write('*');
|
||||||
return;
|
return;
|
||||||
case TypeKind.TypeParameter:
|
case TypeKind.TypeParameter:
|
||||||
var tp = (ITypeParameterSymbol)type;
|
var tp = (ITypeParameterSymbol)type;
|
||||||
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
trapFile.Write('_');
|
trapFile.Write('_');
|
||||||
trapFile.Write(tp.Name);
|
trapFile.Write(tp.Name);
|
||||||
return;
|
return;
|
||||||
@@ -207,7 +202,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType = false)
|
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||||
{
|
{
|
||||||
if (symbol is null)
|
if (symbol is null)
|
||||||
{
|
{
|
||||||
@@ -232,7 +227,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
|
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
|
||||||
trapFile.Write("__self__");
|
trapFile.Write("__self__");
|
||||||
else if (symbol is ITypeSymbol type && type.IdDependsOn(cx, symbolBeingDefined))
|
else if (symbol is ITypeSymbol type && type.IdDependsOn(cx, symbolBeingDefined))
|
||||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
type.BuildTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||||
else if (symbol is INamedTypeSymbol namedType && namedType.IsTupleType && constructUnderlyingTupleType)
|
else if (symbol is INamedTypeSymbol namedType && namedType.IsTupleType && constructUnderlyingTupleType)
|
||||||
trapFile.WriteSubId(NamedType.CreateNamedTypeFromTupleType(cx, namedType));
|
trapFile.WriteSubId(NamedType.CreateNamedTypeFromTupleType(cx, namedType));
|
||||||
else
|
else
|
||||||
@@ -250,7 +245,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
/// <paramref name="symbol" />.
|
/// <paramref name="symbol" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
|
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
|
||||||
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, true);
|
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs an array suffix string for this array type symbol.
|
/// Constructs an array suffix string for this array type symbol.
|
||||||
@@ -287,7 +282,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
|
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
|
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||||
{
|
{
|
||||||
if (!constructUnderlyingTupleType && named.IsTupleType)
|
if (!constructUnderlyingTupleType && named.IsTupleType)
|
||||||
{
|
{
|
||||||
@@ -297,7 +292,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
{
|
{
|
||||||
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
|
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
|
||||||
trapFile.Write(":");
|
trapFile.Write(":");
|
||||||
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
trapFile.Write(")");
|
trapFile.Write(")");
|
||||||
@@ -308,7 +303,7 @@ namespace Semmle.Extraction.CSharp
|
|||||||
{
|
{
|
||||||
if (named.ContainingType is not null)
|
if (named.ContainingType is not null)
|
||||||
{
|
{
|
||||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||||
trapFile.Write('.');
|
trapFile.Write('.');
|
||||||
}
|
}
|
||||||
else if (named.ContainingNamespace is not null)
|
else if (named.ContainingNamespace is not null)
|
||||||
@@ -333,35 +328,17 @@ namespace Semmle.Extraction.CSharp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||||
trapFile.Write('<');
|
trapFile.Write('<');
|
||||||
// Encode the nullability of the type arguments in the label.
|
// Encode the nullability of the type arguments in the label.
|
||||||
// Type arguments with different nullability can result in
|
// Type arguments with different nullability can result in
|
||||||
// a constructed type with different nullability of its members and methods,
|
// a constructed type with different nullability of its members and methods,
|
||||||
// so we need to create a distinct database entity for it.
|
// so we need to create a distinct database entity for it.
|
||||||
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
|
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
|
||||||
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass)
|
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false)
|
||||||
);
|
);
|
||||||
trapFile.Write('>');
|
trapFile.Write('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addBaseClass && named.GetNonObjectBaseType(cx) is INamedTypeSymbol @base)
|
|
||||||
{
|
|
||||||
// We need to limit unfolding of base classes. For example, in
|
|
||||||
//
|
|
||||||
// ```csharp
|
|
||||||
// class C1<T> { }
|
|
||||||
// class C2<T> : C1<C3<T>> { }
|
|
||||||
// class C3<T> : C1<C2<T>> { }
|
|
||||||
// class C4 : C3<C4> { }
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// when we generate the label for `C4`, the base class `C3<C4>` has itself `C1<C2<C4>>` as
|
|
||||||
// a base class, which in turn has `C1<C3<C4>>` as a base class. The latter has the original
|
|
||||||
// base class `C3<C4>` as a type argument, which would lead to infinite unfolding.
|
|
||||||
trapFile.Write(" : ");
|
|
||||||
@base.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass: false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, EscapingTextWriter trapFile)
|
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, EscapingTextWriter trapFile)
|
||||||
|
|||||||
@@ -47,44 +47,6 @@ module Stages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
|
||||||
module DataFlowStage {
|
|
||||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
|
||||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
|
||||||
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
|
|
||||||
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate forceCachingInSameStage() { any() }
|
|
||||||
|
|
||||||
cached
|
|
||||||
private predicate forceCachingInSameStageRev() {
|
|
||||||
defaultAdditionalTaintStep(_, _)
|
|
||||||
or
|
|
||||||
any(ArgumentNode n).argumentOf(_, _)
|
|
||||||
or
|
|
||||||
exists(any(DataFlow::Node n).getEnclosingCallable())
|
|
||||||
or
|
|
||||||
exists(any(DataFlow::Node n).getControlFlowNode())
|
|
||||||
or
|
|
||||||
exists(any(DataFlow::Node n).getType())
|
|
||||||
or
|
|
||||||
exists(any(NodeImpl n).getDataFlowType())
|
|
||||||
or
|
|
||||||
exists(any(DataFlow::Node n).getLocation())
|
|
||||||
or
|
|
||||||
exists(any(DataFlow::Node n).toString())
|
|
||||||
or
|
|
||||||
exists(any(OutNode n).getCall(_))
|
|
||||||
or
|
|
||||||
exists(CallContext cc)
|
|
||||||
or
|
|
||||||
exists(any(DataFlowCall c).getEnclosingCallable())
|
|
||||||
or
|
|
||||||
forceCachingInSameStageRev()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
cached
|
||||||
module UnificationStage {
|
module UnificationStage {
|
||||||
private import semmle.code.csharp.Unification
|
private import semmle.code.csharp.Unification
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
private import csharp
|
private import csharp
|
||||||
private import cil
|
private import cil
|
||||||
private import dotnet
|
private import dotnet
|
||||||
|
private import DataFlowImplCommon as DataFlowImplCommon
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
private import semmle.code.csharp.Caching
|
|
||||||
private import semmle.code.csharp.dataflow.FlowSummary
|
private import semmle.code.csharp.dataflow.FlowSummary
|
||||||
private import semmle.code.csharp.dispatch.Dispatch
|
private import semmle.code.csharp.dispatch.Dispatch
|
||||||
private import semmle.code.csharp.frameworks.system.Collections
|
private import semmle.code.csharp.frameworks.system.Collections
|
||||||
@@ -68,31 +68,30 @@ private predicate transitiveCapturedCallTarget(ControlFlow::Nodes::ElementNode c
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
newtype TReturnKind =
|
||||||
private module Cached {
|
TNormalReturnKind() or
|
||||||
cached
|
TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
|
||||||
newtype TReturnKind =
|
TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
|
||||||
TNormalReturnKind() { Stages::DataFlowStage::forceCachingInSameStage() } or
|
TImplicitCapturedReturnKind(LocalScopeVariable v) {
|
||||||
TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
|
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
|
||||||
TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
|
v = def.getSourceVariable().getAssignable()
|
||||||
TImplicitCapturedReturnKind(LocalScopeVariable v) {
|
)
|
||||||
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
|
} or
|
||||||
v = def.getSourceVariable().getAssignable()
|
TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
|
||||||
)
|
rk instanceof NormalReturnKind and
|
||||||
} or
|
(
|
||||||
TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
|
target instanceof Constructor or
|
||||||
rk instanceof NormalReturnKind and
|
not target.getReturnType() instanceof VoidType
|
||||||
(
|
)
|
||||||
target instanceof Constructor or
|
or
|
||||||
not target.getReturnType() instanceof VoidType
|
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
|
||||||
)
|
}
|
||||||
or
|
|
||||||
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private module Cached {
|
||||||
cached
|
cached
|
||||||
newtype TDataFlowCall =
|
newtype TDataFlowCall =
|
||||||
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
|
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
|
||||||
|
DataFlowImplCommon::forceCachingInSameStage() and
|
||||||
cfn.getElement() = dc.getCall()
|
cfn.getElement() = dc.getCall()
|
||||||
} or
|
} or
|
||||||
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
|
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
|
||||||
@@ -246,7 +245,6 @@ abstract class DataFlowCall extends TDataFlowCall {
|
|||||||
abstract DataFlow::Node getNode();
|
abstract DataFlow::Node getNode();
|
||||||
|
|
||||||
/** Gets the enclosing callable of this call. */
|
/** Gets the enclosing callable of this call. */
|
||||||
cached
|
|
||||||
abstract DataFlowCallable getEnclosingCallable();
|
abstract DataFlowCallable getEnclosingCallable();
|
||||||
|
|
||||||
/** Gets the underlying expression, if any. */
|
/** Gets the underlying expression, if any. */
|
||||||
@@ -280,10 +278,7 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
|
|||||||
|
|
||||||
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
|
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
|
||||||
|
|
||||||
override DataFlowCallable getEnclosingCallable() {
|
override DataFlowCallable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
|
||||||
result = cfn.getEnclosingCallable()
|
|
||||||
}
|
|
||||||
|
|
||||||
override string toString() { result = cfn.toString() }
|
override string toString() { result = cfn.toString() }
|
||||||
|
|
||||||
|
|||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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.
|
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||||
*/
|
*/
|
||||||
private module LambdaFlow {
|
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)
|
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)
|
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 |
|
exists(int i |
|
||||||
viableParamNonLambda(call, i, p) and
|
viableParamNonLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
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 |
|
exists(int i |
|
||||||
viableParamLambda(call, i, p) and
|
viableParamLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
arg.argumentOf(call, i)
|
||||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||||
then compatibleTypes(t, getNodeType(node))
|
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
lambdaCall(lambdaCall, kind, node) and
|
lambdaCall(lambdaCall, kind, node) and
|
||||||
t = getNodeType(node) and
|
t = getNodeDataFlowType(node) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = false and
|
toJump = false and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
|||||||
toJump = true and
|
toJump = true and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
|
|
|
|
||||||
jumpStep(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
or
|
or
|
||||||
exists(boolean preservesValue |
|
exists(boolean preservesValue |
|
||||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow into a callable
|
// 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
|
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||||
(
|
(
|
||||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revLambdaFlowIn(
|
predicate revLambdaFlowIn(
|
||||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||||
DataFlowCallOption lastCall
|
DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module 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`.
|
* 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`.
|
* The instance parameter is considered to have index `-1`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
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)
|
p.isParameterOf(viableCallableExt(call), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +353,11 @@ private module Cached {
|
|||||||
* dispatch into account.
|
* dispatch into account.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
viableParam(call, i, p) and
|
viableParam(call, i, p) and
|
||||||
arg.argumentOf(call, i) 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`.
|
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||||
p = node and
|
p = node and
|
||||||
read = false
|
read = false
|
||||||
or
|
or
|
||||||
@@ -325,30 +408,30 @@ private module Cached {
|
|||||||
// read
|
// read
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
parameterValueFlowCand(p, mid, false) and
|
parameterValueFlowCand(p, mid, false) and
|
||||||
readStep(mid, _, node) and
|
read(mid, _, node) and
|
||||||
read = true
|
read = true
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no prior read
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, false) and
|
parameterValueFlowArgCand(p, arg, false) and
|
||||||
argumentValueFlowsThroughCand(arg, node, read)
|
argumentValueFlowsThroughCand(arg, node, read)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, read) and
|
parameterValueFlowArgCand(p, arg, read) and
|
||||||
argumentValueFlowsThroughCand(arg, node, false)
|
argumentValueFlowsThroughCand(arg, node, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||||
parameterValueFlowCand(p, arg, read)
|
parameterValueFlowCand(p, arg, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
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
|
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||||
* node.
|
* node.
|
||||||
*/
|
*/
|
||||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlowCand(p, ret, read) and
|
parameterValueFlowCand(p, ret, read) and
|
||||||
kind = ret.getKind()
|
kind = ret.getKind()
|
||||||
@@ -369,9 +452,9 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThroughCand0(
|
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)
|
parameterValueFlowReturnCand(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -382,14 +465,14 @@ private module Cached {
|
|||||||
*
|
*
|
||||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
* `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 |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate cand(ParameterNode p, Node n) {
|
predicate cand(ParamNode p, Node n) {
|
||||||
parameterValueFlowCand(p, n, _) and
|
parameterValueFlowCand(p, n, _) and
|
||||||
(
|
(
|
||||||
parameterValueFlowReturnCand(p, _, _)
|
parameterValueFlowReturnCand(p, _, _)
|
||||||
@@ -416,21 +499,21 @@ private module Cached {
|
|||||||
* If a read step was taken, then `read` captures the `Content`, the
|
* If a read step was taken, then `read` captures the `Content`, the
|
||||||
* container type, and the content type.
|
* 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
|
parameterValueFlow0(p, node, read) and
|
||||||
if node instanceof CastingNode
|
if node instanceof CastingNode
|
||||||
then
|
then
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||||
p = node and
|
p = node and
|
||||||
Cand::cand(p, _) and
|
Cand::cand(p, _) and
|
||||||
read = TReadStepTypesNone()
|
read = TReadStepTypesNone()
|
||||||
@@ -447,7 +530,7 @@ private module Cached {
|
|||||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||||
read.getContentType()) and
|
read.getContentType()) and
|
||||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||||
@@ -455,34 +538,32 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0_0(
|
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
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||||
argumentValueFlowsThrough(arg, read, node)
|
argumentValueFlowsThrough(arg, read, node)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, read) and
|
parameterValueFlowArg(p, arg, read) and
|
||||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArg(
|
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
|
||||||
) {
|
|
||||||
parameterValueFlow(p, arg, read) and
|
parameterValueFlow(p, arg, read) and
|
||||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThrough0(
|
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)
|
parameterValueFlowReturn(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -496,18 +577,18 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||||
exists(DataFlowCall call, ReturnKind kind |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
|
|
|
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +597,7 @@ private module Cached {
|
|||||||
* value-preserving steps and a single read step, not taking call
|
* value-preserving steps and a single read step, not taking call
|
||||||
* contexts into account, thus representing a getter-step.
|
* 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)
|
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +610,7 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
private predicate parameterValueFlowReturn(
|
private predicate parameterValueFlowReturn(
|
||||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||||
) {
|
) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlow(p, ret, read) and
|
parameterValueFlow(p, ret, read) and
|
||||||
@@ -553,7 +634,7 @@ private module Cached {
|
|||||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||||
mayBenefitFromCallContext(call, callable)
|
mayBenefitFromCallContext(call, callable)
|
||||||
or
|
or
|
||||||
callable = call.getEnclosingCallable() and
|
callEnclosingCallable(call, callable) and
|
||||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +692,7 @@ private module Cached {
|
|||||||
mayBenefitFromCallContextExt(call, _) and
|
mayBenefitFromCallContextExt(call, _) and
|
||||||
c = viableCallableExt(call) and
|
c = viableCallableExt(call) and
|
||||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) 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
|
ctxtgts < tgts
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -635,8 +716,7 @@ private module Cached {
|
|||||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
* 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.
|
* node `n`, in the same callable, using only value-preserving steps.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
|
||||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +724,9 @@ private module Cached {
|
|||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
storeStep(node1, c, node2) and
|
storeStep(node1, c, node2) and
|
||||||
readStep(_, c, _) and
|
read(_, c, _) and
|
||||||
contentType = getNodeType(node1) and
|
contentType = getNodeDataFlowType(node1) and
|
||||||
containerType = getNodeType(node2)
|
containerType = getNodeDataFlowType(node2)
|
||||||
or
|
or
|
||||||
exists(Node n1, Node n2 |
|
exists(Node n1, Node n2 |
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
@@ -654,12 +734,15 @@ private module Cached {
|
|||||||
|
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
or
|
or
|
||||||
readStep(n2, c, n1) and
|
read(n2, c, n1) and
|
||||||
contentType = getNodeType(n1) and
|
contentType = getNodeDataFlowType(n1) and
|
||||||
containerType = getNodeType(n2)
|
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
|
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||||
* `f`.
|
* `f`.
|
||||||
@@ -678,8 +761,9 @@ private module Cached {
|
|||||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate reverseStepThroughInputOutputAlias(
|
||||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||||
|
) {
|
||||||
exists(Node fromPre, Node toPre |
|
exists(Node fromPre, Node toPre |
|
||||||
fromPre = fromNode.getPreUpdateNode() and
|
fromPre = fromNode.getPreUpdateNode() and
|
||||||
toPre = toNode.getPreUpdateNode()
|
toPre = toNode.getPreUpdateNode()
|
||||||
@@ -688,14 +772,20 @@ private module Cached {
|
|||||||
// Does the language-specific simpleLocalFlowStep already model flow
|
// Does the language-specific simpleLocalFlowStep already model flow
|
||||||
// from function input to output?
|
// from function input to output?
|
||||||
fromPre = getAnOutNode(c, _) and
|
fromPre = getAnOutNode(c, _) and
|
||||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
toPre.(ArgNode).argumentOf(c, _) and
|
||||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
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
|
* Holds if the call context `call` either improves virtual dispatch in
|
||||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
* `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) {
|
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||||
reducedViableImplInCallContext(_, callable, call)
|
reducedViableImplInCallContext(_, callable, call)
|
||||||
or
|
or
|
||||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
@@ -726,12 +816,12 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
newtype TReturnKindExt =
|
||||||
TValueReturn(ReturnKind kind) or
|
TValueReturn(ReturnKind kind) or
|
||||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TBooleanOption =
|
newtype TBooleanOption =
|
||||||
@@ -761,23 +851,15 @@ private module Cached {
|
|||||||
* A `Node` at which a cast can occur such that the type should be checked.
|
* A `Node` at which a cast can occur such that the type should be checked.
|
||||||
*/
|
*/
|
||||||
class CastingNode extends Node {
|
class CastingNode extends Node {
|
||||||
CastingNode() {
|
CastingNode() { castingNode(this) }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate readStepWithTypes(
|
private predicate readStepWithTypes(
|
||||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||||
) {
|
) {
|
||||||
readStep(n1, c, n2) and
|
read(n1, c, n2) and
|
||||||
container = getNodeType(n1) and
|
container = getNodeDataFlowType(n1) and
|
||||||
content = getNodeType(n2)
|
content = getNodeDataFlowType(n2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TReadStepTypesOption =
|
private newtype TReadStepTypesOption =
|
||||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
|||||||
override string toString() { result = "CcSomeCall" }
|
override string toString() { result = "CcSomeCall" }
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
override predicate relevantFor(DataFlowCallable callable) {
|
||||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate matchesCall(DataFlowCall call) { any() }
|
override predicate matchesCall(DataFlowCall call) { any() }
|
||||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
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) {
|
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
|
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
|
* 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.
|
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||||
*/
|
*/
|
||||||
class ReturnNodeExt extends Node {
|
class ReturnNodeExt extends Node {
|
||||||
ReturnNodeExt() {
|
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||||
this instanceof ReturnNode or
|
|
||||||
parameterValueFlowsToPreUpdate(_, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the kind of this returned value. */
|
/** Gets the kind of this returned value. */
|
||||||
ReturnKindExt getKind() {
|
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||||
result = TValueReturn(this.(ReturnNode).getKind())
|
|
||||||
or
|
|
||||||
exists(ParameterNode p, int pos |
|
|
||||||
parameterValueFlowsToPreUpdate(p, this) and
|
|
||||||
p.isParameterOf(_, pos) and
|
|
||||||
result = TParamUpdate(pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
|||||||
* or a post-update node associated with a call argument.
|
* or a post-update node associated with a call argument.
|
||||||
*/
|
*/
|
||||||
class OutNodeExt extends Node {
|
class OutNodeExt extends Node {
|
||||||
OutNodeExt() {
|
OutNodeExt() { outNodeExt(this) }
|
||||||
this instanceof OutNode
|
|
||||||
or
|
|
||||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
|||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
/** Gets a node corresponding to data flow out of `call`. */
|
/** 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 {
|
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
|||||||
ReturnKind getKind() { result = kind }
|
ReturnKind getKind() { result = kind }
|
||||||
|
|
||||||
override string toString() { result = kind.toString() }
|
override string toString() { result = kind.toString() }
|
||||||
|
|
||||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
|
||||||
result = getAnOutNode(call, this.getKind())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
|||||||
int getPosition() { result = pos }
|
int getPosition() { result = pos }
|
||||||
|
|
||||||
override string toString() { result = "param update " + 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. */
|
/** A callable tagged with a relevant return kind. */
|
||||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||||
exists(Node n0 |
|
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
pragma[only_bind_into](n0) = n and
|
}
|
||||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
|
||||||
)
|
/** 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]
|
pragma[noinline]
|
||||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
|||||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||||
or
|
or
|
||||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||||
call0.getEnclosingCallable() = callable and
|
callEnclosingCallable(call0, callable) and
|
||||||
cc = TReturn(c0, call0) and
|
cc = TReturn(c0, call0) and
|
||||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||||
)
|
)
|
||||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
|||||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate read = readStep/3;
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
|||||||
|
|
||||||
TypedContent getHead() { this = TFrontHead(result) }
|
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 {
|
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ private import DataFlowImplCommon
|
|||||||
private import ControlFlowReachability
|
private import ControlFlowReachability
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
private import semmle.code.csharp.dataflow.FlowSummary
|
private import semmle.code.csharp.dataflow.FlowSummary
|
||||||
private import semmle.code.csharp.Caching
|
|
||||||
private import semmle.code.csharp.Conversion
|
private import semmle.code.csharp.Conversion
|
||||||
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
|
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.code.csharp.ExprOrStmtParent
|
private import semmle.code.csharp.ExprOrStmtParent
|
||||||
@@ -21,7 +20,6 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
|
|||||||
|
|
||||||
abstract class NodeImpl extends Node {
|
abstract class NodeImpl extends Node {
|
||||||
/** Do not call: use `getEnclosingCallable()` instead. */
|
/** Do not call: use `getEnclosingCallable()` instead. */
|
||||||
cached
|
|
||||||
abstract DataFlowCallable getEnclosingCallableImpl();
|
abstract DataFlowCallable getEnclosingCallableImpl();
|
||||||
|
|
||||||
/** Do not call: use `getType()` instead. */
|
/** Do not call: use `getType()` instead. */
|
||||||
@@ -29,9 +27,8 @@ abstract class NodeImpl extends Node {
|
|||||||
abstract DotNet::Type getTypeImpl();
|
abstract DotNet::Type getTypeImpl();
|
||||||
|
|
||||||
/** Gets the type of this node used for type pruning. */
|
/** Gets the type of this node used for type pruning. */
|
||||||
cached
|
|
||||||
Gvn::GvnType getDataFlowType() {
|
Gvn::GvnType getDataFlowType() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
forceCachingInSameStage() and
|
||||||
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
|
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
|
||||||
t0 = getCSharpType(this.getType())
|
t0 = getCSharpType(this.getType())
|
||||||
or
|
or
|
||||||
@@ -55,26 +52,25 @@ abstract class NodeImpl extends Node {
|
|||||||
|
|
||||||
private class ExprNodeImpl extends ExprNode, NodeImpl {
|
private class ExprNodeImpl extends ExprNode, NodeImpl {
|
||||||
override DataFlowCallable getEnclosingCallableImpl() {
|
override DataFlowCallable getEnclosingCallableImpl() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
|
||||||
result = this.getExpr().getEnclosingCallable()
|
result = this.getExpr().getEnclosingCallable()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DotNet::Type getTypeImpl() {
|
override DotNet::Type getTypeImpl() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
forceCachingInSameStage() and
|
||||||
result = this.getExpr().getType()
|
result = this.getExpr().getType()
|
||||||
}
|
}
|
||||||
|
|
||||||
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() {
|
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and this = TExprNode(result)
|
forceCachingInSameStage() and this = TExprNode(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Location getLocationImpl() {
|
override Location getLocationImpl() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and result = this.getExpr().getLocation()
|
forceCachingInSameStage() and result = this.getExpr().getLocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toStringImpl() {
|
override string toStringImpl() {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
forceCachingInSameStage() and
|
||||||
result = this.getControlFlowNode().toString()
|
result = this.getControlFlowNodeImpl().toString()
|
||||||
or
|
or
|
||||||
exists(CIL::Expr e |
|
exists(CIL::Expr e |
|
||||||
this = TCilExprNode(e) and
|
this = TCilExprNode(e) and
|
||||||
@@ -394,6 +390,22 @@ module LocalFlow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the local flow predicate that is used as a building block in global
|
||||||
|
* data flow. It excludes SSA flow through instance fields, as flow through fields
|
||||||
|
* is handled by the global data-flow library, but includes various other steps
|
||||||
|
* that are only relevant for global flow.
|
||||||
|
*/
|
||||||
|
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
|
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
|
||||||
|
or
|
||||||
|
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
|
||||||
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private Expr getImplicitArgument(Call c, int pos) {
|
private Expr getImplicitArgument(Call c, int pos) {
|
||||||
result = c.getArgument(pos) and
|
result = c.getArgument(pos) and
|
||||||
@@ -582,12 +594,16 @@ private Type getCSharpType(DotNet::Type t) {
|
|||||||
result.matchesHandle(t)
|
result.matchesHandle(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class RelevantDataFlowType extends DataFlowType {
|
||||||
|
RelevantDataFlowType() { this = any(NodeImpl n).getDataFlowType() }
|
||||||
|
}
|
||||||
|
|
||||||
/** A GVN type that is either a `DataFlowType` or unifiable with a `DataFlowType`. */
|
/** A GVN type that is either a `DataFlowType` or unifiable with a `DataFlowType`. */
|
||||||
private class DataFlowTypeOrUnifiable extends Gvn::GvnType {
|
private class DataFlowTypeOrUnifiable extends Gvn::GvnType {
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlowTypeOrUnifiable() {
|
DataFlowTypeOrUnifiable() {
|
||||||
this instanceof DataFlowType or
|
this instanceof RelevantDataFlowType or
|
||||||
Gvn::unifiable(any(DataFlowType t), this)
|
Gvn::unifiable(any(RelevantDataFlowType t), this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,7 +614,7 @@ private TypeParameter getATypeParameterSubType(DataFlowTypeOrUnifiable t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private TypeParameter getATypeParameterSubTypeRestricted(DataFlowType t) {
|
private TypeParameter getATypeParameterSubTypeRestricted(RelevantDataFlowType t) {
|
||||||
result = getATypeParameterSubType(t)
|
result = getATypeParameterSubType(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,17 +630,30 @@ private Gvn::GvnType getANonTypeParameterSubType(DataFlowTypeOrUnifiable t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private Gvn::GvnType getANonTypeParameterSubTypeRestricted(DataFlowType t) {
|
private Gvn::GvnType getANonTypeParameterSubTypeRestricted(RelevantDataFlowType t) {
|
||||||
result = getANonTypeParameterSubType(t)
|
result = getANonTypeParameterSubType(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A collection of cached types and predicates to be evaluated in the same stage. */
|
/** A collection of cached types and predicates to be evaluated in the same stage. */
|
||||||
cached
|
cached
|
||||||
private module Cached {
|
private module Cached {
|
||||||
|
private import TaintTrackingPrivate as TaintTrackingPrivate
|
||||||
|
|
||||||
|
// Add artificial dependencies to enforce all cached predicates are evaluated
|
||||||
|
// in the "DataFlowImplCommon stage"
|
||||||
|
private predicate forceCaching() {
|
||||||
|
TaintTrackingPrivate::forceCachingInSameStage() or
|
||||||
|
exists(any(NodeImpl n).getTypeImpl()) or
|
||||||
|
exists(any(NodeImpl n).getControlFlowNodeImpl()) or
|
||||||
|
exists(any(NodeImpl n).getLocationImpl()) or
|
||||||
|
exists(any(NodeImpl n).toStringImpl())
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TNode =
|
newtype TNode =
|
||||||
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
|
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and cfn.getElement() instanceof Expr
|
forceCaching() and
|
||||||
|
cfn.getElement() instanceof Expr
|
||||||
} or
|
} or
|
||||||
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
|
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
|
||||||
TSsaDefinitionNode(Ssa::Definition def) {
|
TSsaDefinitionNode(Ssa::Definition def) {
|
||||||
@@ -679,23 +708,6 @@ private module Cached {
|
|||||||
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
|
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the local flow predicate that is used as a building block in global
|
|
||||||
* data flow. It excludes SSA flow through instance fields, as flow through fields
|
|
||||||
* is handled by the global data-flow library, but includes various other steps
|
|
||||||
* that are only relevant for global flow.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
|
||||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
|
|
||||||
or
|
|
||||||
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
|
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
|
||||||
* (intra-procedural) step.
|
* (intra-procedural) step.
|
||||||
@@ -714,178 +726,14 @@ private module Cached {
|
|||||||
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
|
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `pred` can flow to `succ`, by jumping from one callable to
|
|
||||||
* another. Additional steps specified by the configuration are *not*
|
|
||||||
* taken into account.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate jumpStepImpl(Node pred, Node succ) {
|
|
||||||
pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
|
|
||||||
or
|
|
||||||
exists(FieldOrProperty fl, FieldOrPropertyRead flr |
|
|
||||||
fl.isStatic() and
|
|
||||||
fl.isFieldLike() and
|
|
||||||
fl.getAnAssignedValue() = pred.asExpr() and
|
|
||||||
fl.getAnAccess() = flr and
|
|
||||||
flr = succ.asExpr() and
|
|
||||||
flr.hasNonlocalValue()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(JumpReturnKind jrk, DataFlowCall call |
|
|
||||||
FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
|
|
||||||
viableCallable(call) = jrk.getTarget() and
|
|
||||||
succ = getAnOutNode(call, jrk.getTargetReturnKind())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TContent =
|
newtype TContent =
|
||||||
TFieldContent(Field f) { f.isUnboundDeclaration() } or
|
TFieldContent(Field f) { f.isUnboundDeclaration() } or
|
||||||
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
|
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
|
||||||
TElementContent()
|
TElementContent()
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if data can flow from `node1` to `node2` via an assignment to
|
|
||||||
* content `c`.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate storeStepImpl(Node node1, Content c, Node node2) {
|
|
||||||
exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
|
|
||||||
hasNodePath(x, node1, node) and
|
|
||||||
if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
|
|
||||||
|
|
|
||||||
fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
|
|
||||||
or
|
|
||||||
arrayStore(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(StoreStepConfiguration x, Expr arg, ControlFlow::Node callCfn |
|
|
||||||
x.hasExprPath(arg, node1.(ExprNode).getControlFlowNode(), _, callCfn) and
|
|
||||||
node2 = TParamsArgumentNode(callCfn) and
|
|
||||||
isParamsArg(_, arg, _) and
|
|
||||||
c instanceof ElementContent
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(Expr e |
|
|
||||||
e = node1.asExpr() and
|
|
||||||
node2.(YieldReturnNode).getYieldReturnStmt().getExpr() = e and
|
|
||||||
c instanceof ElementContent
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(Expr e |
|
|
||||||
e = node1.asExpr() and
|
|
||||||
node2.(AsyncReturnNode).getExpr() = e and
|
|
||||||
c = getResultContent()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private PropertyContent getResultContent() {
|
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, RelevantDataFlowType t2) {
|
||||||
result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate readStepImpl(Node node1, Content c, Node node2) {
|
|
||||||
exists(ReadStepConfiguration x |
|
|
||||||
hasNodePath(x, node1, node2) and
|
|
||||||
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
|
||||||
or
|
|
||||||
hasNodePath(x, node1, node2) and
|
|
||||||
arrayRead(node1.asExpr(), node2.asExpr()) and
|
|
||||||
c instanceof ElementContent
|
|
||||||
or
|
|
||||||
exists(ForeachStmt fs, Ssa::ExplicitDefinition def |
|
|
||||||
x.hasDefPath(fs.getIterableExpr(), node1.getControlFlowNode(), def.getADefinition(),
|
|
||||||
def.getControlFlowNode()) and
|
|
||||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
|
||||||
c instanceof ElementContent
|
|
||||||
)
|
|
||||||
or
|
|
||||||
hasNodePath(x, node1, node2) and
|
|
||||||
node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
|
|
||||||
c = getResultContent()
|
|
||||||
or
|
|
||||||
// node1 = (..., node2, ...)
|
|
||||||
// node1.ItemX flows to node2
|
|
||||||
exists(TupleExpr te, int i, Expr item |
|
|
||||||
te = node1.asExpr() and
|
|
||||||
not te.isConstruction() and
|
|
||||||
c.(FieldContent).getField() = te.getType().(TupleType).getElement(i).getUnboundDeclaration() and
|
|
||||||
// node1 = (..., item, ...)
|
|
||||||
te.getArgument(i) = item
|
|
||||||
|
|
|
||||||
// item = (..., ..., ...) in node1 = (..., (..., ..., ...), ...)
|
|
||||||
node2.asExpr().(TupleExpr) = item and
|
|
||||||
hasNodePath(x, node1, node2)
|
|
||||||
or
|
|
||||||
// item = variable in node1 = (..., variable, ...)
|
|
||||||
exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
|
|
||||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
|
||||||
def.getADefinition() = tad and
|
|
||||||
tad.getLeaf() = item and
|
|
||||||
hasNodePath(x, node1, node2)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
|
|
||||||
te = any(PatternExpr pe).getAChildExpr*() and
|
|
||||||
exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
|
|
||||||
node2.(SsaDefinitionNode).getDefinition() = def and
|
|
||||||
def.getADefinition() = lvd and
|
|
||||||
lvd.getDeclaration() = item and
|
|
||||||
hasNodePath(x, node1, node2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
|
||||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
|
||||||
* in `x.f = newValue`.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate clearsContent(Node n, Content c) {
|
|
||||||
fieldOrPropertyStore(_, c, _, n.asExpr(), true)
|
|
||||||
or
|
|
||||||
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) and
|
|
||||||
not c instanceof ElementContent
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
|
|
||||||
or
|
|
||||||
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
|
|
||||||
oi = we.getInitializer() and
|
|
||||||
n.asExpr() = oi and
|
|
||||||
f = oi.getAMemberInitializer().getInitializedMember() and
|
|
||||||
c = f.getContent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if the node `n` is unreachable when the call context is `call`.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
predicate isUnreachableInCall(Node n, DataFlowCall call) {
|
|
||||||
exists(
|
|
||||||
ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
|
|
||||||
|
|
|
||||||
viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
|
|
||||||
paramNode.getSsaDefinition().getARead() = guard and
|
|
||||||
guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, DataFlowType t2) {
|
|
||||||
not t1 instanceof Gvn::TypeParameterGvnType and
|
not t1 instanceof Gvn::TypeParameterGvnType and
|
||||||
t1 = t2
|
t1 = t2
|
||||||
or
|
or
|
||||||
@@ -899,102 +747,53 @@ private module Cached {
|
|||||||
* `t2` are allowed to be type parameters.
|
* `t2` are allowed to be type parameters.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate commonSubType(DataFlowType t1, DataFlowType t2) { commonSubTypeGeneral(t1, t2) }
|
predicate commonSubType(RelevantDataFlowType t1, RelevantDataFlowType t2) {
|
||||||
|
commonSubTypeGeneral(t1, t2)
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
predicate commonSubTypeUnifiableLeft(DataFlowType t1, DataFlowType t2) {
|
predicate commonSubTypeUnifiableLeft(RelevantDataFlowType t1, RelevantDataFlowType t2) {
|
||||||
exists(Gvn::GvnType t |
|
exists(Gvn::GvnType t |
|
||||||
Gvn::unifiable(t1, t) and
|
Gvn::unifiable(t1, t) and
|
||||||
commonSubTypeGeneral(t, t2)
|
commonSubTypeGeneral(t, t2)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
|
||||||
predicate outRefReturnNode(Ssa::ExplicitDefinition def, OutRefReturnKind kind) {
|
|
||||||
exists(Parameter p |
|
|
||||||
def.isLiveOutRefParameterDefinition(p) and
|
|
||||||
kind.getPosition() = p.getPosition()
|
|
||||||
|
|
|
||||||
p.isOut() and kind instanceof OutReturnKind
|
|
||||||
or
|
|
||||||
p.isRef() and kind instanceof RefReturnKind
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryOutNodeCached(DataFlowCall c, Node out, ReturnKind rk) {
|
|
||||||
FlowSummaryImpl::Private::summaryOutNode(c, out, rk)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryArgumentNodeCached(DataFlowCall c, Node arg, int i) {
|
|
||||||
FlowSummaryImpl::Private::summaryArgumentNode(c, arg, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryPostUpdateNodeCached(Node post, ParameterNode pre) {
|
|
||||||
FlowSummaryImpl::Private::summaryPostUpdateNode(post, pre)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryReturnNodeCached(Node ret, ReturnKind rk) {
|
|
||||||
FlowSummaryImpl::Private::summaryReturnNode(ret, rk) and
|
|
||||||
not rk instanceof JumpReturnKind
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate castNode(Node n) {
|
|
||||||
n.asExpr() instanceof Cast
|
|
||||||
or
|
|
||||||
n.(AssignableDefinitionNode).getDefinition() instanceof AssignableDefinitions::PatternDefinition
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if `n` should be hidden from path explanations. */
|
|
||||||
cached
|
|
||||||
predicate nodeIsHidden(Node n) {
|
|
||||||
exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
|
|
||||||
def instanceof Ssa::PhiNode
|
|
||||||
or
|
|
||||||
def instanceof Ssa::ImplicitEntryDefinition
|
|
||||||
or
|
|
||||||
def instanceof Ssa::ImplicitCallDefinition
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(Parameter p |
|
|
||||||
p = n.(ParameterNode).getParameter() and
|
|
||||||
not p.fromSource()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
n = TInstanceParameterNode(any(Callable c | not c.fromSource()))
|
|
||||||
or
|
|
||||||
n instanceof YieldReturnNode
|
|
||||||
or
|
|
||||||
n instanceof AsyncReturnNode
|
|
||||||
or
|
|
||||||
n instanceof ImplicitCapturedArgumentNode
|
|
||||||
or
|
|
||||||
n instanceof MallocNode
|
|
||||||
or
|
|
||||||
n instanceof SummaryNode
|
|
||||||
or
|
|
||||||
n instanceof ParamsArgumentNode
|
|
||||||
or
|
|
||||||
n.asExpr() = any(WithExpr we).getInitializer()
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate parameterNode(Node n, DataFlowCallable c, int i) {
|
|
||||||
n.(ParameterNodeImpl).isParameterOf(c, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate argumentNode(Node n, DataFlowCall call, int pos) {
|
|
||||||
n.(ArgumentNodeImpl).argumentOf(call, pos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import Cached
|
import Cached
|
||||||
|
|
||||||
|
/** Holds if `n` should be hidden from path explanations. */
|
||||||
|
predicate nodeIsHidden(Node n) {
|
||||||
|
exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
|
||||||
|
def instanceof Ssa::PhiNode
|
||||||
|
or
|
||||||
|
def instanceof Ssa::ImplicitEntryDefinition
|
||||||
|
or
|
||||||
|
def instanceof Ssa::ImplicitCallDefinition
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Parameter p |
|
||||||
|
p = n.(ParameterNode).getParameter() and
|
||||||
|
not p.fromSource()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
n = TInstanceParameterNode(any(Callable c | not c.fromSource()))
|
||||||
|
or
|
||||||
|
n instanceof YieldReturnNode
|
||||||
|
or
|
||||||
|
n instanceof AsyncReturnNode
|
||||||
|
or
|
||||||
|
n instanceof ImplicitCapturedArgumentNode
|
||||||
|
or
|
||||||
|
n instanceof MallocNode
|
||||||
|
or
|
||||||
|
n instanceof SummaryNode
|
||||||
|
or
|
||||||
|
n instanceof ParamsArgumentNode
|
||||||
|
or
|
||||||
|
n.asExpr() = any(WithExpr we).getInitializer()
|
||||||
|
}
|
||||||
|
|
||||||
/** An SSA definition, viewed as a node in a data flow graph. */
|
/** An SSA definition, viewed as a node in a data flow graph. */
|
||||||
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
|
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
|
||||||
Ssa::Definition def;
|
Ssa::Definition def;
|
||||||
@@ -1142,10 +941,12 @@ import ParameterNodes
|
|||||||
|
|
||||||
/** A data-flow node that represents a call argument. */
|
/** A data-flow node that represents a call argument. */
|
||||||
class ArgumentNode extends Node {
|
class ArgumentNode extends Node {
|
||||||
ArgumentNode() { argumentNode(this, _, _) }
|
ArgumentNode() { this instanceof ArgumentNodeImpl }
|
||||||
|
|
||||||
/** Holds if this argument occurs at the given position in the given call. */
|
/** 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, int pos) {
|
||||||
|
this.(ArgumentNodeImpl).argumentOf(call, pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract private class ArgumentNodeImpl extends Node {
|
abstract private class ArgumentNodeImpl extends Node {
|
||||||
@@ -1310,14 +1111,10 @@ private module ArgumentNodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
|
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
|
||||||
private DataFlowCall c;
|
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
|
||||||
private int i;
|
|
||||||
|
|
||||||
SummaryArgumentNode() { summaryArgumentNodeCached(c, this, i) }
|
|
||||||
|
|
||||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||||
call = c and
|
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
|
||||||
i = pos
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1352,7 +1149,16 @@ private module ReturnNodes {
|
|||||||
class OutRefReturnNode extends ReturnNode, SsaDefinitionNode {
|
class OutRefReturnNode extends ReturnNode, SsaDefinitionNode {
|
||||||
OutRefReturnKind kind;
|
OutRefReturnKind kind;
|
||||||
|
|
||||||
OutRefReturnNode() { outRefReturnNode(this.getDefinition(), kind) }
|
OutRefReturnNode() {
|
||||||
|
exists(Parameter p |
|
||||||
|
this.getDefinition().isLiveOutRefParameterDefinition(p) and
|
||||||
|
kind.getPosition() = p.getPosition()
|
||||||
|
|
|
||||||
|
p.isOut() and kind instanceof OutReturnKind
|
||||||
|
or
|
||||||
|
p.isRef() and kind instanceof RefReturnKind
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override ReturnKind getKind() { result = kind }
|
override ReturnKind getKind() { result = kind }
|
||||||
}
|
}
|
||||||
@@ -1449,7 +1255,10 @@ private module ReturnNodes {
|
|||||||
private class SummaryReturnNode extends SummaryNode, ReturnNode {
|
private class SummaryReturnNode extends SummaryNode, ReturnNode {
|
||||||
private ReturnKind rk;
|
private ReturnKind rk;
|
||||||
|
|
||||||
SummaryReturnNode() { summaryReturnNodeCached(this, rk) }
|
SummaryReturnNode() {
|
||||||
|
FlowSummaryImpl::Private::summaryReturnNode(this, rk) and
|
||||||
|
not rk instanceof JumpReturnKind
|
||||||
|
}
|
||||||
|
|
||||||
override ReturnKind getKind() { result = rk }
|
override ReturnKind getKind() { result = rk }
|
||||||
}
|
}
|
||||||
@@ -1460,7 +1269,6 @@ import ReturnNodes
|
|||||||
/** A data-flow node that represents the output of a call. */
|
/** A data-flow node that represents the output of a call. */
|
||||||
abstract class OutNode extends Node {
|
abstract class OutNode extends Node {
|
||||||
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
|
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
|
||||||
cached
|
|
||||||
abstract DataFlowCall getCall(ReturnKind kind);
|
abstract DataFlowCall getCall(ReturnKind kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1488,7 +1296,6 @@ private module OutNodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlowCall getCall(ReturnKind kind) {
|
override DataFlowCall getCall(ReturnKind kind) {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
|
||||||
result = call and
|
result = call and
|
||||||
(
|
(
|
||||||
kind instanceof NormalReturnKind and
|
kind instanceof NormalReturnKind and
|
||||||
@@ -1564,14 +1371,10 @@ private module OutNodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SummaryOutNode extends SummaryNode, OutNode {
|
private class SummaryOutNode extends SummaryNode, OutNode {
|
||||||
private DataFlowCall c;
|
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
|
||||||
private ReturnKind rk;
|
|
||||||
|
|
||||||
SummaryOutNode() { summaryOutNodeCached(c, this, rk) }
|
|
||||||
|
|
||||||
override DataFlowCall getCall(ReturnKind kind) {
|
override DataFlowCall getCall(ReturnKind kind) {
|
||||||
result = c and
|
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
|
||||||
kind = rk
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1654,7 +1457,29 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate jumpStep = jumpStepImpl/2;
|
/**
|
||||||
|
* Holds if `pred` can flow to `succ`, by jumping from one callable to
|
||||||
|
* another. Additional steps specified by the configuration are *not*
|
||||||
|
* taken into account.
|
||||||
|
*/
|
||||||
|
predicate jumpStep(Node pred, Node succ) {
|
||||||
|
pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
|
||||||
|
or
|
||||||
|
exists(FieldOrProperty fl, FieldOrPropertyRead flr |
|
||||||
|
fl.isStatic() and
|
||||||
|
fl.isFieldLike() and
|
||||||
|
fl.getAnAssignedValue() = pred.asExpr() and
|
||||||
|
fl.getAnAccess() = flr and
|
||||||
|
flr = succ.asExpr() and
|
||||||
|
flr.hasNonlocalValue()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(JumpReturnKind jrk, DataFlowCall call |
|
||||||
|
FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
|
||||||
|
viableCallable(call) = jrk.getTarget() and
|
||||||
|
succ = getAnOutNode(call, jrk.getTargetReturnKind())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
|
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
|
||||||
StoreStepConfiguration() { this = "StoreStepConfiguration" }
|
StoreStepConfiguration() { this = "StoreStepConfiguration" }
|
||||||
@@ -1675,7 +1500,46 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate storeStep = storeStepImpl/3;
|
pragma[nomagic]
|
||||||
|
private PropertyContent getResultContent() {
|
||||||
|
result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if data can flow from `node1` to `node2` via an assignment to
|
||||||
|
* content `c`.
|
||||||
|
*/
|
||||||
|
predicate storeStep(Node node1, Content c, Node node2) {
|
||||||
|
exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
|
||||||
|
hasNodePath(x, node1, node) and
|
||||||
|
if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
|
||||||
|
|
|
||||||
|
fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
|
||||||
|
or
|
||||||
|
arrayStore(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(StoreStepConfiguration x, Expr arg, ControlFlow::Node callCfn |
|
||||||
|
x.hasExprPath(arg, node1.(ExprNode).getControlFlowNode(), _, callCfn) and
|
||||||
|
node2 = TParamsArgumentNode(callCfn) and
|
||||||
|
isParamsArg(_, arg, _) and
|
||||||
|
c instanceof ElementContent
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Expr e |
|
||||||
|
e = node1.asExpr() and
|
||||||
|
node2.(YieldReturnNode).getYieldReturnStmt().getExpr() = e and
|
||||||
|
c instanceof ElementContent
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Expr e |
|
||||||
|
e = node1.asExpr() and
|
||||||
|
node2.(AsyncReturnNode).getExpr() = e and
|
||||||
|
c = getResultContent()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
|
||||||
|
}
|
||||||
|
|
||||||
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
|
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
|
||||||
ReadStepConfiguration() { this = "ReadStepConfiguration" }
|
ReadStepConfiguration() { this = "ReadStepConfiguration" }
|
||||||
@@ -1742,7 +1606,99 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate readStep = readStepImpl/3;
|
/**
|
||||||
|
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
|
||||||
|
*/
|
||||||
|
predicate readStep(Node node1, Content c, Node node2) {
|
||||||
|
exists(ReadStepConfiguration x |
|
||||||
|
hasNodePath(x, node1, node2) and
|
||||||
|
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||||
|
or
|
||||||
|
hasNodePath(x, node1, node2) and
|
||||||
|
arrayRead(node1.asExpr(), node2.asExpr()) and
|
||||||
|
c instanceof ElementContent
|
||||||
|
or
|
||||||
|
exists(ForeachStmt fs, Ssa::ExplicitDefinition def |
|
||||||
|
x.hasDefPath(fs.getIterableExpr(), node1.getControlFlowNode(), def.getADefinition(),
|
||||||
|
def.getControlFlowNode()) and
|
||||||
|
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||||
|
c instanceof ElementContent
|
||||||
|
)
|
||||||
|
or
|
||||||
|
hasNodePath(x, node1, node2) and
|
||||||
|
node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
|
||||||
|
c = getResultContent()
|
||||||
|
or
|
||||||
|
// node1 = (..., node2, ...)
|
||||||
|
// node1.ItemX flows to node2
|
||||||
|
exists(TupleExpr te, int i, Expr item |
|
||||||
|
te = node1.asExpr() and
|
||||||
|
not te.isConstruction() and
|
||||||
|
c.(FieldContent).getField() = te.getType().(TupleType).getElement(i).getUnboundDeclaration() and
|
||||||
|
// node1 = (..., item, ...)
|
||||||
|
te.getArgument(i) = item
|
||||||
|
|
|
||||||
|
// item = (..., ..., ...) in node1 = (..., (..., ..., ...), ...)
|
||||||
|
node2.asExpr().(TupleExpr) = item and
|
||||||
|
hasNodePath(x, node1, node2)
|
||||||
|
or
|
||||||
|
// item = variable in node1 = (..., variable, ...)
|
||||||
|
exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
|
||||||
|
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||||
|
def.getADefinition() = tad and
|
||||||
|
tad.getLeaf() = item and
|
||||||
|
hasNodePath(x, node1, node2)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
|
||||||
|
te = any(PatternExpr pe).getAChildExpr*() and
|
||||||
|
exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
|
||||||
|
node2.(SsaDefinitionNode).getDefinition() = def and
|
||||||
|
def.getADefinition() = lvd and
|
||||||
|
lvd.getDeclaration() = item and
|
||||||
|
hasNodePath(x, node1, node2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||||
|
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||||
|
* in `x.f = newValue`.
|
||||||
|
*/
|
||||||
|
predicate clearsContent(Node n, Content c) {
|
||||||
|
fieldOrPropertyStore(_, c, _, n.asExpr(), true)
|
||||||
|
or
|
||||||
|
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) and
|
||||||
|
not c instanceof ElementContent
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
|
||||||
|
or
|
||||||
|
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
|
||||||
|
oi = we.getInitializer() and
|
||||||
|
n.asExpr() = oi and
|
||||||
|
f = oi.getAMemberInitializer().getInitializedMember() and
|
||||||
|
c = f.getContent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the node `n` is unreachable when the call context is `call`.
|
||||||
|
*/
|
||||||
|
predicate isUnreachableInCall(Node n, DataFlowCall call) {
|
||||||
|
exists(
|
||||||
|
ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
|
||||||
|
|
|
||||||
|
viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
|
||||||
|
paramNode.getSsaDefinition().getARead() = guard and
|
||||||
|
guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An entity used to represent the type of data-flow node. Two nodes will have
|
* An entity used to represent the type of data-flow node. Two nodes will have
|
||||||
@@ -1753,10 +1709,7 @@ predicate readStep = readStepImpl/3;
|
|||||||
* `DataFlowType`, while `Func<T, int>` and `Func<string, int>` are not, because
|
* `DataFlowType`, while `Func<T, int>` and `Func<string, int>` are not, because
|
||||||
* `string` is not a type parameter.
|
* `string` is not a type parameter.
|
||||||
*/
|
*/
|
||||||
class DataFlowType extends Gvn::GvnType {
|
class DataFlowType = Gvn::GvnType;
|
||||||
pragma[nomagic]
|
|
||||||
DataFlowType() { this = any(NodeImpl n).getDataFlowType() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the type of `n` used for type pruning. */
|
/** Gets the type of `n` used for type pruning. */
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
@@ -1888,11 +1841,11 @@ private module PostUpdateNodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
|
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
|
||||||
private Node pre;
|
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) }
|
||||||
|
|
||||||
SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
|
override Node getPreUpdateNode() {
|
||||||
|
FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
|
||||||
override Node getPreUpdateNode() { result = pre }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1900,7 +1853,12 @@ private import PostUpdateNodes
|
|||||||
|
|
||||||
/** A node that performs a type cast. */
|
/** A node that performs a type cast. */
|
||||||
class CastNode extends Node {
|
class CastNode extends Node {
|
||||||
CastNode() { castNode(this) }
|
CastNode() {
|
||||||
|
this.asExpr() instanceof Cast
|
||||||
|
or
|
||||||
|
this.(AssignableDefinitionNode).getDefinition() instanceof
|
||||||
|
AssignableDefinitions::PatternDefinition
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataFlowExpr = DotNet::Expr;
|
class DataFlowExpr = DotNet::Expr;
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ class Node extends TNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TExprNode_ = TExprNode or TCilExprNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An expression, viewed as a node in a data flow graph.
|
* An expression, viewed as a node in a data flow graph.
|
||||||
*
|
*
|
||||||
@@ -74,9 +76,7 @@ class Node extends TNode {
|
|||||||
* to multiple `ExprNode`s, just like it may correspond to multiple
|
* to multiple `ExprNode`s, just like it may correspond to multiple
|
||||||
* `ControlFlow::Node`s.
|
* `ControlFlow::Node`s.
|
||||||
*/
|
*/
|
||||||
class ExprNode extends Node {
|
class ExprNode extends Node, TExprNode_ {
|
||||||
ExprNode() { this = TExprNode(_) or this = TCilExprNode(_) }
|
|
||||||
|
|
||||||
/** Gets the expression corresponding to this node. */
|
/** Gets the expression corresponding to this node. */
|
||||||
DotNet::Expr getExpr() {
|
DotNet::Expr getExpr() {
|
||||||
result = this.getExprAtNode(_)
|
result = this.getExprAtNode(_)
|
||||||
@@ -99,7 +99,7 @@ class ExprNode extends Node {
|
|||||||
* flow graph.
|
* flow graph.
|
||||||
*/
|
*/
|
||||||
class ParameterNode extends Node {
|
class ParameterNode extends Node {
|
||||||
ParameterNode() { parameterNode(this, _, _) }
|
ParameterNode() { this instanceof ParameterNodeImpl }
|
||||||
|
|
||||||
/** Gets the parameter corresponding to this node, if any. */
|
/** Gets the parameter corresponding to this node, if any. */
|
||||||
DotNet::Parameter getParameter() {
|
DotNet::Parameter getParameter() {
|
||||||
@@ -110,7 +110,9 @@ class ParameterNode extends Node {
|
|||||||
* Holds if this node is the parameter of callable `c` at the specified
|
* Holds if this node is the parameter of callable `c` at the specified
|
||||||
* (zero-based) position.
|
* (zero-based) position.
|
||||||
*/
|
*/
|
||||||
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
|
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||||
|
this.(ParameterNodeImpl).isParameterOf(c, i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A definition, viewed as a node in a data flow graph. */
|
/** A definition, viewed as a node in a data flow graph. */
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
private import csharp
|
private import csharp
|
||||||
private import TaintTrackingPublic
|
private import TaintTrackingPublic
|
||||||
private import DataFlowImplCommon
|
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
private import semmle.code.csharp.Caching
|
private import semmle.code.csharp.Caching
|
||||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||||
@@ -79,7 +78,6 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
|
||||||
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
|
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
|
||||||
or
|
or
|
||||||
localTaintStepCil(nodeFrom, nodeTo)
|
localTaintStepCil(nodeFrom, nodeTo)
|
||||||
@@ -87,6 +85,11 @@ private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node n
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module Cached {
|
private module Cached {
|
||||||
|
private import DataFlowImplCommon as DataFlowImplCommon
|
||||||
|
|
||||||
|
cached
|
||||||
|
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||||
* (intra-procedural) step.
|
* (intra-procedural) step.
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ function_pointer_return_type(
|
|||||||
int return_type_id: @type_or_ref ref);
|
int return_type_id: @type_or_ref ref);
|
||||||
|
|
||||||
extend(
|
extend(
|
||||||
unique int sub: @type ref,
|
int sub: @type ref,
|
||||||
int super: @type_or_ref ref);
|
int super: @type_or_ref ref);
|
||||||
|
|
||||||
anonymous_types(
|
anonymous_types(
|
||||||
|
|||||||
@@ -613,13 +613,13 @@ foreach.cs:
|
|||||||
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
|
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
|
||||||
# 5| r5_29(Int32) = Constant[7] :
|
# 5| r5_29(Int32) = Constant[7] :
|
||||||
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
|
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
|
||||||
# 7| r7_1(glval<IEnumerator>) = VariableAddress[#temp7:9] :
|
# 7| r7_1(glval<Boolean>) = VariableAddress[#temp7:9] :
|
||||||
# 7| r7_2(glval<Int32[]>) = VariableAddress[a_array] :
|
# 7| r7_2(glval<Int32[]>) = VariableAddress[a_array] :
|
||||||
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
|
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
|
||||||
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
|
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
|
||||||
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
|
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
|
||||||
# 7| mu7_6(<unknown>) = ^CallSideEffect : ~m?
|
# 7| mu7_6(<unknown>) = ^CallSideEffect : ~m?
|
||||||
# 7| mu7_7(IEnumerator) = Store[#temp7:9] : &:r7_1, r7_5
|
# 7| mu7_7(Boolean) = Store[#temp7:9] : &:r7_1, r7_5
|
||||||
#-----| Goto -> Block 1
|
#-----| Goto -> Block 1
|
||||||
|
|
||||||
# 7| Block 1
|
# 7| Block 1
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Removed unique base class constraint
|
||||||
|
compatibility: backwards
|
||||||
3
java/change-notes/2021-05-05-kryo-improvements.md
Normal file
3
java/change-notes/2021-05-05-kryo-improvements.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* Add support for version 5 of the Kryo serialization/deserialization framework.
|
||||||
|
* Add support for detecting safe uses of Kryo utilizing `KryoPool.Builder`. [#4992](https://github.com/github/codeql/issues/4992)
|
||||||
2
java/change-notes/2021-05-12-xxe-fp-fix.md
Normal file
2
java/change-notes/2021-05-12-xxe-fp-fix.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
lgtm,codescanning
|
||||||
|
* The query "Resolving XML external entity in user-controlled data" (`java/xxe`) has been improved to report fewer false positives when a Builder / Factory (e.g. an `XMLInputFactory`) is configured safely by using a boxed boolean as second argument to one or more of its configuration methods.
|
||||||
@@ -292,6 +292,7 @@ private predicate summaryModelCsv(string row) {
|
|||||||
"java.util;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
|
"java.util;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
|
||||||
"java.beans;XMLDecoder;false;XMLDecoder;;;Argument[0];Argument[-1];taint",
|
"java.beans;XMLDecoder;false;XMLDecoder;;;Argument[0];Argument[-1];taint",
|
||||||
"com.esotericsoftware.kryo.io;Input;false;Input;;;Argument[0];Argument[-1];taint",
|
"com.esotericsoftware.kryo.io;Input;false;Input;;;Argument[0];Argument[-1];taint",
|
||||||
|
"com.esotericsoftware.kryo5.io;Input;false;Input;;;Argument[0];Argument[-1];taint",
|
||||||
"java.io;BufferedInputStream;false;BufferedInputStream;;;Argument[0];Argument[-1];taint",
|
"java.io;BufferedInputStream;false;BufferedInputStream;;;Argument[0];Argument[-1];taint",
|
||||||
"java.io;DataInputStream;false;DataInputStream;;;Argument[0];Argument[-1];taint",
|
"java.io;DataInputStream;false;DataInputStream;;;Argument[0];Argument[-1];taint",
|
||||||
"java.io;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint",
|
"java.io;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint",
|
||||||
|
|||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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.
|
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||||
*/
|
*/
|
||||||
private module LambdaFlow {
|
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)
|
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)
|
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 |
|
exists(int i |
|
||||||
viableParamNonLambda(call, i, p) and
|
viableParamNonLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
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 |
|
exists(int i |
|
||||||
viableParamLambda(call, i, p) and
|
viableParamLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
arg.argumentOf(call, i)
|
||||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||||
then compatibleTypes(t, getNodeType(node))
|
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
lambdaCall(lambdaCall, kind, node) and
|
lambdaCall(lambdaCall, kind, node) and
|
||||||
t = getNodeType(node) and
|
t = getNodeDataFlowType(node) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = false and
|
toJump = false and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
|||||||
toJump = true and
|
toJump = true and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
|
|
|
|
||||||
jumpStep(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
or
|
or
|
||||||
exists(boolean preservesValue |
|
exists(boolean preservesValue |
|
||||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow into a callable
|
// 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
|
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||||
(
|
(
|
||||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revLambdaFlowIn(
|
predicate revLambdaFlowIn(
|
||||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||||
DataFlowCallOption lastCall
|
DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module 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`.
|
* 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`.
|
* The instance parameter is considered to have index `-1`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
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)
|
p.isParameterOf(viableCallableExt(call), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +353,11 @@ private module Cached {
|
|||||||
* dispatch into account.
|
* dispatch into account.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
viableParam(call, i, p) and
|
viableParam(call, i, p) and
|
||||||
arg.argumentOf(call, i) 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`.
|
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||||
p = node and
|
p = node and
|
||||||
read = false
|
read = false
|
||||||
or
|
or
|
||||||
@@ -325,30 +408,30 @@ private module Cached {
|
|||||||
// read
|
// read
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
parameterValueFlowCand(p, mid, false) and
|
parameterValueFlowCand(p, mid, false) and
|
||||||
readStep(mid, _, node) and
|
read(mid, _, node) and
|
||||||
read = true
|
read = true
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no prior read
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, false) and
|
parameterValueFlowArgCand(p, arg, false) and
|
||||||
argumentValueFlowsThroughCand(arg, node, read)
|
argumentValueFlowsThroughCand(arg, node, read)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, read) and
|
parameterValueFlowArgCand(p, arg, read) and
|
||||||
argumentValueFlowsThroughCand(arg, node, false)
|
argumentValueFlowsThroughCand(arg, node, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||||
parameterValueFlowCand(p, arg, read)
|
parameterValueFlowCand(p, arg, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
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
|
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||||
* node.
|
* node.
|
||||||
*/
|
*/
|
||||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlowCand(p, ret, read) and
|
parameterValueFlowCand(p, ret, read) and
|
||||||
kind = ret.getKind()
|
kind = ret.getKind()
|
||||||
@@ -369,9 +452,9 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThroughCand0(
|
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)
|
parameterValueFlowReturnCand(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -382,14 +465,14 @@ private module Cached {
|
|||||||
*
|
*
|
||||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
* `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 |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate cand(ParameterNode p, Node n) {
|
predicate cand(ParamNode p, Node n) {
|
||||||
parameterValueFlowCand(p, n, _) and
|
parameterValueFlowCand(p, n, _) and
|
||||||
(
|
(
|
||||||
parameterValueFlowReturnCand(p, _, _)
|
parameterValueFlowReturnCand(p, _, _)
|
||||||
@@ -416,21 +499,21 @@ private module Cached {
|
|||||||
* If a read step was taken, then `read` captures the `Content`, the
|
* If a read step was taken, then `read` captures the `Content`, the
|
||||||
* container type, and the content type.
|
* 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
|
parameterValueFlow0(p, node, read) and
|
||||||
if node instanceof CastingNode
|
if node instanceof CastingNode
|
||||||
then
|
then
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||||
p = node and
|
p = node and
|
||||||
Cand::cand(p, _) and
|
Cand::cand(p, _) and
|
||||||
read = TReadStepTypesNone()
|
read = TReadStepTypesNone()
|
||||||
@@ -447,7 +530,7 @@ private module Cached {
|
|||||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||||
read.getContentType()) and
|
read.getContentType()) and
|
||||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||||
@@ -455,34 +538,32 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0_0(
|
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
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||||
argumentValueFlowsThrough(arg, read, node)
|
argumentValueFlowsThrough(arg, read, node)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, read) and
|
parameterValueFlowArg(p, arg, read) and
|
||||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArg(
|
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
|
||||||
) {
|
|
||||||
parameterValueFlow(p, arg, read) and
|
parameterValueFlow(p, arg, read) and
|
||||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThrough0(
|
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)
|
parameterValueFlowReturn(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -496,18 +577,18 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||||
exists(DataFlowCall call, ReturnKind kind |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
|
|
|
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +597,7 @@ private module Cached {
|
|||||||
* value-preserving steps and a single read step, not taking call
|
* value-preserving steps and a single read step, not taking call
|
||||||
* contexts into account, thus representing a getter-step.
|
* 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)
|
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +610,7 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
private predicate parameterValueFlowReturn(
|
private predicate parameterValueFlowReturn(
|
||||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||||
) {
|
) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlow(p, ret, read) and
|
parameterValueFlow(p, ret, read) and
|
||||||
@@ -553,7 +634,7 @@ private module Cached {
|
|||||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||||
mayBenefitFromCallContext(call, callable)
|
mayBenefitFromCallContext(call, callable)
|
||||||
or
|
or
|
||||||
callable = call.getEnclosingCallable() and
|
callEnclosingCallable(call, callable) and
|
||||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +692,7 @@ private module Cached {
|
|||||||
mayBenefitFromCallContextExt(call, _) and
|
mayBenefitFromCallContextExt(call, _) and
|
||||||
c = viableCallableExt(call) and
|
c = viableCallableExt(call) and
|
||||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) 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
|
ctxtgts < tgts
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -635,8 +716,7 @@ private module Cached {
|
|||||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
* 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.
|
* node `n`, in the same callable, using only value-preserving steps.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
|
||||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +724,9 @@ private module Cached {
|
|||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
storeStep(node1, c, node2) and
|
storeStep(node1, c, node2) and
|
||||||
readStep(_, c, _) and
|
read(_, c, _) and
|
||||||
contentType = getNodeType(node1) and
|
contentType = getNodeDataFlowType(node1) and
|
||||||
containerType = getNodeType(node2)
|
containerType = getNodeDataFlowType(node2)
|
||||||
or
|
or
|
||||||
exists(Node n1, Node n2 |
|
exists(Node n1, Node n2 |
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
@@ -654,12 +734,15 @@ private module Cached {
|
|||||||
|
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
or
|
or
|
||||||
readStep(n2, c, n1) and
|
read(n2, c, n1) and
|
||||||
contentType = getNodeType(n1) and
|
contentType = getNodeDataFlowType(n1) and
|
||||||
containerType = getNodeType(n2)
|
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
|
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||||
* `f`.
|
* `f`.
|
||||||
@@ -678,8 +761,9 @@ private module Cached {
|
|||||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate reverseStepThroughInputOutputAlias(
|
||||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||||
|
) {
|
||||||
exists(Node fromPre, Node toPre |
|
exists(Node fromPre, Node toPre |
|
||||||
fromPre = fromNode.getPreUpdateNode() and
|
fromPre = fromNode.getPreUpdateNode() and
|
||||||
toPre = toNode.getPreUpdateNode()
|
toPre = toNode.getPreUpdateNode()
|
||||||
@@ -688,14 +772,20 @@ private module Cached {
|
|||||||
// Does the language-specific simpleLocalFlowStep already model flow
|
// Does the language-specific simpleLocalFlowStep already model flow
|
||||||
// from function input to output?
|
// from function input to output?
|
||||||
fromPre = getAnOutNode(c, _) and
|
fromPre = getAnOutNode(c, _) and
|
||||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
toPre.(ArgNode).argumentOf(c, _) and
|
||||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
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
|
* Holds if the call context `call` either improves virtual dispatch in
|
||||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
* `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) {
|
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||||
reducedViableImplInCallContext(_, callable, call)
|
reducedViableImplInCallContext(_, callable, call)
|
||||||
or
|
or
|
||||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
@@ -726,12 +816,12 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
newtype TReturnKindExt =
|
||||||
TValueReturn(ReturnKind kind) or
|
TValueReturn(ReturnKind kind) or
|
||||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TBooleanOption =
|
newtype TBooleanOption =
|
||||||
@@ -761,23 +851,15 @@ private module Cached {
|
|||||||
* A `Node` at which a cast can occur such that the type should be checked.
|
* A `Node` at which a cast can occur such that the type should be checked.
|
||||||
*/
|
*/
|
||||||
class CastingNode extends Node {
|
class CastingNode extends Node {
|
||||||
CastingNode() {
|
CastingNode() { castingNode(this) }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate readStepWithTypes(
|
private predicate readStepWithTypes(
|
||||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||||
) {
|
) {
|
||||||
readStep(n1, c, n2) and
|
read(n1, c, n2) and
|
||||||
container = getNodeType(n1) and
|
container = getNodeDataFlowType(n1) and
|
||||||
content = getNodeType(n2)
|
content = getNodeDataFlowType(n2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TReadStepTypesOption =
|
private newtype TReadStepTypesOption =
|
||||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
|||||||
override string toString() { result = "CcSomeCall" }
|
override string toString() { result = "CcSomeCall" }
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
override predicate relevantFor(DataFlowCallable callable) {
|
||||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate matchesCall(DataFlowCall call) { any() }
|
override predicate matchesCall(DataFlowCall call) { any() }
|
||||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
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) {
|
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
|
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
|
* 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.
|
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||||
*/
|
*/
|
||||||
class ReturnNodeExt extends Node {
|
class ReturnNodeExt extends Node {
|
||||||
ReturnNodeExt() {
|
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||||
this instanceof ReturnNode or
|
|
||||||
parameterValueFlowsToPreUpdate(_, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the kind of this returned value. */
|
/** Gets the kind of this returned value. */
|
||||||
ReturnKindExt getKind() {
|
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||||
result = TValueReturn(this.(ReturnNode).getKind())
|
|
||||||
or
|
|
||||||
exists(ParameterNode p, int pos |
|
|
||||||
parameterValueFlowsToPreUpdate(p, this) and
|
|
||||||
p.isParameterOf(_, pos) and
|
|
||||||
result = TParamUpdate(pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
|||||||
* or a post-update node associated with a call argument.
|
* or a post-update node associated with a call argument.
|
||||||
*/
|
*/
|
||||||
class OutNodeExt extends Node {
|
class OutNodeExt extends Node {
|
||||||
OutNodeExt() {
|
OutNodeExt() { outNodeExt(this) }
|
||||||
this instanceof OutNode
|
|
||||||
or
|
|
||||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
|||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
/** Gets a node corresponding to data flow out of `call`. */
|
/** 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 {
|
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
|||||||
ReturnKind getKind() { result = kind }
|
ReturnKind getKind() { result = kind }
|
||||||
|
|
||||||
override string toString() { result = kind.toString() }
|
override string toString() { result = kind.toString() }
|
||||||
|
|
||||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
|
||||||
result = getAnOutNode(call, this.getKind())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
|||||||
int getPosition() { result = pos }
|
int getPosition() { result = pos }
|
||||||
|
|
||||||
override string toString() { result = "param update " + 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. */
|
/** A callable tagged with a relevant return kind. */
|
||||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||||
exists(Node n0 |
|
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
pragma[only_bind_into](n0) = n and
|
}
|
||||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
|
||||||
)
|
/** 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]
|
pragma[noinline]
|
||||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
|||||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||||
or
|
or
|
||||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||||
call0.getEnclosingCallable() = callable and
|
callEnclosingCallable(call0, callable) and
|
||||||
cc = TReturn(c0, call0) and
|
cc = TReturn(c0, call0) and
|
||||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||||
)
|
)
|
||||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
|||||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate read = readStep/3;
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
|||||||
|
|
||||||
TypedContent getHead() { this = TFrontHead(result) }
|
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 {
|
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||||
|
|||||||
@@ -4,71 +4,48 @@ private import semmle.code.java.dataflow.FlowSummary
|
|||||||
private import semmle.code.java.dataflow.TypeFlow
|
private import semmle.code.java.dataflow.TypeFlow
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
|
private import DataFlowImplCommon as DataFlowImplCommon
|
||||||
|
|
||||||
cached
|
cached
|
||||||
private module Cached {
|
newtype TNode =
|
||||||
cached
|
TExprNode(Expr e) {
|
||||||
newtype TNode =
|
DataFlowImplCommon::forceCachingInSameStage() and
|
||||||
TExprNode(Expr e) {
|
not e.getType() instanceof VoidType and
|
||||||
not e.getType() instanceof VoidType and
|
not e.getParent*() instanceof Annotation
|
||||||
not e.getParent*() instanceof Annotation
|
} or
|
||||||
} or
|
TExplicitParameterNode(Parameter p) {
|
||||||
TExplicitParameterNode(Parameter p) {
|
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
|
||||||
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
|
} or
|
||||||
} or
|
TImplicitVarargsArray(Call c) {
|
||||||
TImplicitVarargsArray(Call c) {
|
c.getCallee().isVarargs() and
|
||||||
c.getCallee().isVarargs() and
|
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
|
||||||
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
|
} or
|
||||||
} or
|
TInstanceParameterNode(Callable c) {
|
||||||
TInstanceParameterNode(Callable c) {
|
(exists(c.getBody()) or c instanceof SummarizedCallable) and
|
||||||
(exists(c.getBody()) or c instanceof SummarizedCallable) and
|
not c.isStatic()
|
||||||
not c.isStatic()
|
} or
|
||||||
} or
|
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
|
||||||
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
|
TMallocNode(ClassInstanceExpr cie) or
|
||||||
TMallocNode(ClassInstanceExpr cie) or
|
TExplicitExprPostUpdate(Expr e) {
|
||||||
TExplicitExprPostUpdate(Expr e) {
|
explicitInstanceArgument(_, e)
|
||||||
explicitInstanceArgument(_, e)
|
or
|
||||||
or
|
e instanceof Argument and not e.getType() instanceof ImmutableType
|
||||||
e instanceof Argument and not e.getType() instanceof ImmutableType
|
or
|
||||||
or
|
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
|
||||||
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
|
or
|
||||||
or
|
exists(ArrayAccess aa | e = aa.getArray())
|
||||||
exists(ArrayAccess aa | e = aa.getArray())
|
} or
|
||||||
} or
|
TImplicitExprPostUpdate(InstanceAccessExt ia) {
|
||||||
TImplicitExprPostUpdate(InstanceAccessExt ia) {
|
implicitInstanceArgument(_, ia)
|
||||||
implicitInstanceArgument(_, ia)
|
or
|
||||||
or
|
exists(FieldAccess fa |
|
||||||
exists(FieldAccess fa |
|
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
|
||||||
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
|
)
|
||||||
)
|
} or
|
||||||
} or
|
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
||||||
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
FlowSummaryImpl::Private::summaryNodeRange(c, state)
|
||||||
FlowSummaryImpl::Private::summaryNodeRange(c, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryOutNodeCached(DataFlowCall c, Node out) {
|
|
||||||
FlowSummaryImpl::Private::summaryOutNode(c, out, _)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryArgumentNodeCached(DataFlowCall c, Node arg, int i) {
|
|
||||||
FlowSummaryImpl::Private::summaryArgumentNode(c, arg, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryPostUpdateNodeCached(Node post, ParameterNode pre) {
|
|
||||||
FlowSummaryImpl::Private::summaryPostUpdateNode(post, pre)
|
|
||||||
}
|
|
||||||
|
|
||||||
cached
|
|
||||||
predicate summaryReturnNodeCached(Node ret) {
|
|
||||||
FlowSummaryImpl::Private::summaryReturnNode(ret, _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private import Cached
|
|
||||||
|
|
||||||
private predicate explicitInstanceArgument(Call call, Expr instarg) {
|
private predicate explicitInstanceArgument(Call call, Expr instarg) {
|
||||||
call instanceof MethodAccess and
|
call instanceof MethodAccess and
|
||||||
instarg = call.getQualifier() and
|
instarg = call.getQualifier() and
|
||||||
@@ -404,13 +381,15 @@ module Private {
|
|||||||
override string toString() { result = "[summary] " + state + " in " + c }
|
override string toString() { result = "[summary] " + state + " in " + c }
|
||||||
|
|
||||||
/** Holds if this summary node is the `i`th argument of `call`. */
|
/** Holds if this summary node is the `i`th argument of `call`. */
|
||||||
predicate isArgumentOf(DataFlowCall call, int i) { summaryArgumentNodeCached(call, this, i) }
|
predicate isArgumentOf(DataFlowCall call, int i) {
|
||||||
|
FlowSummaryImpl::Private::summaryArgumentNode(call, this, i)
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if this summary node is a return node. */
|
/** Holds if this summary node is a return node. */
|
||||||
predicate isReturn() { summaryReturnNodeCached(this) }
|
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this, _) }
|
||||||
|
|
||||||
/** Holds if this summary node is an out node for `call`. */
|
/** Holds if this summary node is an out node for `call`. */
|
||||||
predicate isOut(DataFlowCall call) { summaryOutNodeCached(call, this) }
|
predicate isOut(DataFlowCall call) { FlowSummaryImpl::Private::summaryOutNode(call, this, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
||||||
@@ -439,7 +418,7 @@ private class MallocNode extends Node, TMallocNode {
|
|||||||
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
|
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
|
||||||
private Node pre;
|
private Node pre;
|
||||||
|
|
||||||
SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
|
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
|
||||||
|
|
||||||
override Node getPreUpdateNode() { result = pre }
|
override Node getPreUpdateNode() { result = pre }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,7 +284,6 @@ private class ConstantBooleanArgumentNode extends ArgumentNode, ExprNode {
|
|||||||
/**
|
/**
|
||||||
* Holds if the node `n` is unreachable when the call context is `call`.
|
* Holds if the node `n` is unreachable when the call context is `call`.
|
||||||
*/
|
*/
|
||||||
cached
|
|
||||||
predicate isUnreachableInCall(Node n, DataFlowCall call) {
|
predicate isUnreachableInCall(Node n, DataFlowCall call) {
|
||||||
exists(
|
exists(
|
||||||
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param,
|
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ private import semmle.code.java.dataflow.FlowSteps
|
|||||||
private import semmle.code.java.dataflow.FlowSummary
|
private import semmle.code.java.dataflow.FlowSummary
|
||||||
import semmle.code.java.dataflow.InstanceAccess
|
import semmle.code.java.dataflow.InstanceAccess
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
|
private import TaintTrackingUtil as TaintTrackingUtil
|
||||||
import DataFlowNodes::Public
|
import DataFlowNodes::Public
|
||||||
|
|
||||||
/** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */
|
/** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */
|
||||||
@@ -112,6 +113,7 @@ predicate localFlowStep(Node node1, Node node2) {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate simpleLocalFlowStep(Node node1, Node node2) {
|
predicate simpleLocalFlowStep(Node node1, Node node2) {
|
||||||
|
TaintTrackingUtil::forceCachingInSameStage() and
|
||||||
// Variable flow steps through adjacent def-use and use-use pairs.
|
// Variable flow steps through adjacent def-use and use-use pairs.
|
||||||
exists(SsaExplicitUpdate upd |
|
exists(SsaExplicitUpdate upd |
|
||||||
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
|
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
|
||||||
|
|||||||
@@ -29,55 +29,69 @@ predicate localExprTaint(Expr src, Expr sink) {
|
|||||||
localTaint(DataFlow::exprNode(src), DataFlow::exprNode(sink))
|
localTaint(DataFlow::exprNode(src), DataFlow::exprNode(sink))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
cached
|
||||||
* Holds if taint can flow in one local step from `src` to `sink`.
|
private module Cached {
|
||||||
*/
|
private import DataFlowImplCommon as DataFlowImplCommon
|
||||||
predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
|
||||||
DataFlow::localFlowStep(src, sink) or
|
cached
|
||||||
localAdditionalTaintStep(src, sink) or
|
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
|
||||||
// Simple flow through library code is included in the exposed local
|
|
||||||
// step relation, even though flow is technically inter-procedural
|
/**
|
||||||
FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
|
* Holds if taint can flow in one local step from `src` to `sink`.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||||
|
DataFlow::localFlowStep(src, sink) or
|
||||||
|
localAdditionalTaintStep(src, sink) or
|
||||||
|
// Simple flow through library code is included in the exposed local
|
||||||
|
// step relation, even though flow is technically inter-procedural
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if taint can flow in one local step from `src` to `sink` excluding
|
||||||
|
* local data flow steps. That is, `src` and `sink` are likely to represent
|
||||||
|
* different objects.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||||
|
localAdditionalTaintExprStep(src.asExpr(), sink.asExpr())
|
||||||
|
or
|
||||||
|
localAdditionalTaintUpdateStep(src.asExpr(),
|
||||||
|
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
|
||||||
|
or
|
||||||
|
exists(Argument arg |
|
||||||
|
src.asExpr() = arg and
|
||||||
|
arg.isVararg() and
|
||||||
|
sink.(DataFlow::ImplicitVarargsArray).getCall() = arg.getCall()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the additional step from `src` to `sink` should be included in all
|
||||||
|
* global taint flow configurations.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||||
|
localAdditionalTaintStep(src, sink) or
|
||||||
|
any(AdditionalTaintStep a).step(src, sink)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` should be a sanitizer in all global taint flow configurations
|
||||||
|
* but not in local taint.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate defaultTaintSanitizer(DataFlow::Node node) {
|
||||||
|
// Ignore paths through test code.
|
||||||
|
node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
|
||||||
|
node.asExpr() instanceof ValidatedVariableAccess
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
import Cached
|
||||||
* Holds if taint can flow in one local step from `src` to `sink` excluding
|
|
||||||
* local data flow steps. That is, `src` and `sink` are likely to represent
|
|
||||||
* different objects.
|
|
||||||
*/
|
|
||||||
predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
|
||||||
localAdditionalTaintExprStep(src.asExpr(), sink.asExpr())
|
|
||||||
or
|
|
||||||
localAdditionalTaintUpdateStep(src.asExpr(),
|
|
||||||
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
|
|
||||||
or
|
|
||||||
exists(Argument arg |
|
|
||||||
src.asExpr() = arg and
|
|
||||||
arg.isVararg() and
|
|
||||||
sink.(DataFlow::ImplicitVarargsArray).getCall() = arg.getCall()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if the additional step from `src` to `sink` should be included in all
|
|
||||||
* global taint flow configurations.
|
|
||||||
*/
|
|
||||||
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
|
||||||
localAdditionalTaintStep(src, sink) or
|
|
||||||
any(AdditionalTaintStep a).step(src, sink)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `node` should be a sanitizer in all global taint flow configurations
|
|
||||||
* but not in local taint.
|
|
||||||
*/
|
|
||||||
predicate defaultTaintSanitizer(DataFlow::Node node) {
|
|
||||||
// Ignore paths through test code.
|
|
||||||
node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
|
|
||||||
node.asExpr() instanceof ValidatedVariableAccess
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if taint can flow in one local step from `src` to `sink` excluding
|
* Holds if taint can flow in one local step from `src` to `sink` excluding
|
||||||
|
|||||||
@@ -3,19 +3,60 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
|
private import semmle.code.java.dataflow.DataFlow
|
||||||
|
private import semmle.code.java.dataflow.FlowSteps
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type `com.esotericsoftware.kryo.Kryo`.
|
* The type `com.esotericsoftware.kryo.Kryo`.
|
||||||
*/
|
*/
|
||||||
class Kryo extends RefType {
|
class Kryo extends RefType {
|
||||||
Kryo() { this.hasQualifiedName("com.esotericsoftware.kryo", "Kryo") }
|
Kryo() {
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo", "Kryo") or
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo5", "Kryo")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Kryo input stream.
|
* A Kryo input stream.
|
||||||
*/
|
*/
|
||||||
class KryoInput extends RefType {
|
class KryoInput extends RefType {
|
||||||
KryoInput() { this.hasQualifiedName("com.esotericsoftware.kryo.io", "Input") }
|
KryoInput() {
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo.io", "Input") or
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo5.io", "Input")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kryo pool.
|
||||||
|
*/
|
||||||
|
class KryoPool extends RefType {
|
||||||
|
KryoPool() {
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool") or
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kryo pool builder.
|
||||||
|
*/
|
||||||
|
class KryoPoolBuilder extends RefType {
|
||||||
|
KryoPoolBuilder() {
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool$Builder") or
|
||||||
|
hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool$Builder")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Kryo pool builder method used in a fluent API call chain.
|
||||||
|
*/
|
||||||
|
class KryoPoolBuilderMethod extends Method {
|
||||||
|
KryoPoolBuilderMethod() {
|
||||||
|
getDeclaringType() instanceof KryoPoolBuilder and
|
||||||
|
(
|
||||||
|
getReturnType() instanceof KryoPoolBuilder or
|
||||||
|
getReturnType() instanceof KryoPool
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,3 +86,13 @@ class KryoEnableWhiteListing extends MethodAccess {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A KryoPool method that uses a Kryo instance.
|
||||||
|
*/
|
||||||
|
class KryoPoolRunMethod extends Method {
|
||||||
|
KryoPoolRunMethod() {
|
||||||
|
getDeclaringType() instanceof KryoPool and
|
||||||
|
hasName("run")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,6 +48,65 @@ class SafeKryo extends DataFlow2::Configuration {
|
|||||||
ma.getMethod() instanceof KryoReadObjectMethod
|
ma.getMethod() instanceof KryoReadObjectMethod
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or
|
||||||
|
stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or
|
||||||
|
stepKryoPoolBuilderChainMethod(node1, node2) or
|
||||||
|
stepKryoPoolBorrowMethod(node1, node2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds when a functional expression is used to create a `KryoPool.Builder`.
|
||||||
|
* Eg. `new KryoPool.Builder(() -> new Kryo())`
|
||||||
|
*/
|
||||||
|
private predicate stepKryoPoolBuilderFactoryArgToConstructor(
|
||||||
|
DataFlow::Node node1, DataFlow::Node node2
|
||||||
|
) {
|
||||||
|
exists(ConstructorCall cc, FunctionalExpr fe |
|
||||||
|
cc.getConstructedType() instanceof KryoPoolBuilder and
|
||||||
|
fe.asMethod().getBody().getAStmt().(ReturnStmt).getResult() = node1.asExpr() and
|
||||||
|
node2.asExpr() = cc and
|
||||||
|
cc.getArgument(0) = fe
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds when a `KryoPool.run` is called to use a `Kryo` instance.
|
||||||
|
* Eg. `pool.run(kryo -> ...)`
|
||||||
|
*/
|
||||||
|
private predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(
|
||||||
|
DataFlow::Node node1, DataFlow::Node node2
|
||||||
|
) {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod() instanceof KryoPoolRunMethod and
|
||||||
|
node1.asExpr() = ma.getQualifier() and
|
||||||
|
ma.getArgument(0).(FunctionalExpr).asMethod().getParameter(0) = node2.asParameter()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds when a `KryoPool.Builder` method is called fluently.
|
||||||
|
*/
|
||||||
|
private predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod() instanceof KryoPoolBuilderMethod and
|
||||||
|
ma = node2.asExpr() and
|
||||||
|
ma.getQualifier() = node1.asExpr()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds when a `KryoPool.borrow` method is called.
|
||||||
|
*/
|
||||||
|
private predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod() =
|
||||||
|
any(Method m | m.getDeclaringType() instanceof KryoPool and m.hasName("borrow")) and
|
||||||
|
node1.asExpr() = ma.getQualifier() and
|
||||||
|
node2.asExpr() = ma
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
|
predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ abstract class ParserConfig extends MethodAccess {
|
|||||||
*/
|
*/
|
||||||
predicate disables(Expr e) {
|
predicate disables(Expr e) {
|
||||||
this.getArgument(0) = e and
|
this.getArgument(0) = e and
|
||||||
this.getArgument(1).(BooleanLiteral).getBooleanValue() = false
|
(
|
||||||
|
this.getArgument(1).(BooleanLiteral).getBooleanValue() = false or
|
||||||
|
this.getArgument(1).(FieldAccess).getField().hasQualifiedName("java.lang", "Boolean", "FALSE")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +47,10 @@ abstract class ParserConfig extends MethodAccess {
|
|||||||
*/
|
*/
|
||||||
predicate enables(Expr e) {
|
predicate enables(Expr e) {
|
||||||
this.getArgument(0) = e and
|
this.getArgument(0) = e and
|
||||||
this.getArgument(1).(BooleanLiteral).getBooleanValue() = true
|
(
|
||||||
|
this.getArgument(1).(BooleanLiteral).getBooleanValue() = true or
|
||||||
|
this.getArgument(1).(FieldAccess).getField().hasQualifiedName("java.lang", "Boolean", "TRUE")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
java/ql/test/query-tests/security/CWE-502/KryoTest.java
Normal file
34
java/ql/test/query-tests/security/CWE-502/KryoTest.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.Socket;
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
import com.esotericsoftware.kryo.pool.KryoPool;
|
||||||
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
|
|
||||||
|
public class KryoTest {
|
||||||
|
|
||||||
|
private Kryo getSafeKryo() {
|
||||||
|
Kryo kryo = new Kryo();
|
||||||
|
kryo.setRegistrationRequired(true);
|
||||||
|
// ... kryo.register(A.class) ...
|
||||||
|
return kryo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void kryoDeserialize(Socket sock) throws java.io.IOException {
|
||||||
|
KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
|
||||||
|
Input input = new Input(sock.getInputStream());
|
||||||
|
Object o = kryoPool.run(kryo -> kryo.readClassAndObject(input)); // OK
|
||||||
|
}
|
||||||
|
|
||||||
|
public void kryoDeserialize2(Socket sock) throws java.io.IOException {
|
||||||
|
KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
|
||||||
|
Input input = new Input(sock.getInputStream());
|
||||||
|
Kryo k = kryoPool.borrow();
|
||||||
|
try {
|
||||||
|
Object o = k.readClassAndObject(input); // OK
|
||||||
|
} finally {
|
||||||
|
kryoPool.release(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.esotericsoftware.kryo.pool;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
|
||||||
|
public interface KryoCallback<T> {
|
||||||
|
T execute (Kryo kryo);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.esotericsoftware.kryo.pool;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
|
||||||
|
public interface KryoFactory {
|
||||||
|
Kryo create ();
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.esotericsoftware.kryo.pool;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
public interface KryoPool {
|
||||||
|
|
||||||
|
Kryo borrow ();
|
||||||
|
|
||||||
|
void release (Kryo kryo);
|
||||||
|
|
||||||
|
<T> T run (KryoCallback<T> callback);
|
||||||
|
|
||||||
|
static class Builder {
|
||||||
|
public Builder (KryoFactory factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder queue (Queue<Kryo> queue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder softReferences () {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KryoPool build () {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,16 +6,13 @@ import javascript
|
|||||||
|
|
||||||
module Base64 {
|
module Base64 {
|
||||||
/** A call to a base64 encoder. */
|
/** A call to a base64 encoder. */
|
||||||
class Encode extends DataFlow::Node {
|
class Encode extends DataFlow::Node instanceof Encode::Range {
|
||||||
Encode::Range encode;
|
|
||||||
|
|
||||||
Encode() { this = encode }
|
|
||||||
|
|
||||||
/** Gets the input passed to the encoder. */
|
/** Gets the input passed to the encoder. */
|
||||||
DataFlow::Node getInput() { result = encode.getInput() }
|
DataFlow::Node getInput() { result = super.getInput() }
|
||||||
|
|
||||||
/** Gets the base64-encoded output of the encoder. */
|
/** Gets the base64-encoded output of the encoder. */
|
||||||
DataFlow::Node getOutput() { result = encode.getOutput() }
|
DataFlow::Node getOutput() { result = super.getOutput() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module Encode {
|
module Encode {
|
||||||
@@ -34,16 +31,13 @@ module Base64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A call to a base64 decoder. */
|
/** A call to a base64 decoder. */
|
||||||
class Decode extends DataFlow::Node {
|
class Decode extends DataFlow::Node instanceof Decode::Range {
|
||||||
Decode::Range encode;
|
|
||||||
|
|
||||||
Decode() { this = encode }
|
|
||||||
|
|
||||||
/** Gets the base64-encoded input passed to the decoder. */
|
/** Gets the base64-encoded input passed to the decoder. */
|
||||||
DataFlow::Node getInput() { result = encode.getInput() }
|
DataFlow::Node getInput() { result = super.getInput() }
|
||||||
|
|
||||||
/** Gets the output of the decoder. */
|
/** Gets the output of the decoder. */
|
||||||
DataFlow::Node getOutput() { result = encode.getOutput() }
|
DataFlow::Node getOutput() { result = super.getOutput() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module Decode {
|
module Decode {
|
||||||
|
|||||||
@@ -8,15 +8,14 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* A reference to a Closure namespace.
|
* A reference to a Closure namespace.
|
||||||
*/
|
*/
|
||||||
class ClosureNamespaceRef extends DataFlow::Node {
|
class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range {
|
||||||
ClosureNamespaceRef::Range range;
|
|
||||||
|
|
||||||
ClosureNamespaceRef() { this = range }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the namespace being referenced.
|
* Gets the namespace being referenced.
|
||||||
*/
|
*/
|
||||||
string getClosureNamespace() { result = range.getClosureNamespace() }
|
string getClosureNamespace() {
|
||||||
|
result = super.getClosureNamespace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module ClosureNamespaceRef {
|
module ClosureNamespaceRef {
|
||||||
@@ -36,8 +35,7 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* A data flow node that returns the value of a closure namespace.
|
* A data flow node that returns the value of a closure namespace.
|
||||||
*/
|
*/
|
||||||
class ClosureNamespaceAccess extends ClosureNamespaceRef {
|
class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range {
|
||||||
override ClosureNamespaceAccess::Range range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module ClosureNamespaceAccess {
|
module ClosureNamespaceAccess {
|
||||||
@@ -80,8 +78,7 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* A top-level call to `goog.provide`.
|
* A top-level call to `goog.provide`.
|
||||||
*/
|
*/
|
||||||
class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode {
|
class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall {
|
||||||
override DefaultClosureProvideCall range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,8 +91,7 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* A call to `goog.require`.
|
* A call to `goog.require`.
|
||||||
*/
|
*/
|
||||||
class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode {
|
class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall {
|
||||||
override DefaultClosureRequireCall range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,8 +107,7 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* A top-level call to `goog.module` or `goog.declareModuleId`.
|
* A top-level call to `goog.module` or `goog.declareModuleId`.
|
||||||
*/
|
*/
|
||||||
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode {
|
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration {
|
||||||
override DefaultClosureModuleDeclaration range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) }
|
private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) }
|
||||||
|
|||||||
@@ -16,16 +16,13 @@ private import javascript
|
|||||||
* ~A.indexOf(B)
|
* ~A.indexOf(B)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class InclusionTest extends DataFlow::Node {
|
class InclusionTest extends DataFlow::Node instanceof InclusionTest::Range {
|
||||||
InclusionTest::Range range;
|
|
||||||
|
|
||||||
InclusionTest() { this = range }
|
|
||||||
|
|
||||||
/** Gets the `A` in `A.includes(B)`. */
|
/** Gets the `A` in `A.includes(B)`. */
|
||||||
DataFlow::Node getContainerNode() { result = range.getContainerNode() }
|
DataFlow::Node getContainerNode() { result = super.getContainerNode() }
|
||||||
|
|
||||||
/** Gets the `B` in `A.includes(B)`. */
|
/** Gets the `B` in `A.includes(B)`. */
|
||||||
DataFlow::Node getContainedNode() { result = range.getContainedNode() }
|
DataFlow::Node getContainedNode() { result = super.getContainedNode() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the polarity of the check.
|
* Gets the polarity of the check.
|
||||||
@@ -33,7 +30,7 @@ class InclusionTest extends DataFlow::Node {
|
|||||||
* If the polarity is `false` the check returns `true` if the container does not contain
|
* If the polarity is `false` the check returns `true` if the container does not contain
|
||||||
* the given element.
|
* the given element.
|
||||||
*/
|
*/
|
||||||
boolean getPolarity() { result = range.getPolarity() }
|
boolean getPolarity() { result = super.getPolarity() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module InclusionTest {
|
module InclusionTest {
|
||||||
|
|||||||
@@ -9,27 +9,24 @@ import javascript
|
|||||||
*
|
*
|
||||||
* Additional candidates can be added by subclassing `MembershipCandidate::Range`
|
* Additional candidates can be added by subclassing `MembershipCandidate::Range`
|
||||||
*/
|
*/
|
||||||
class MembershipCandidate extends DataFlow::Node {
|
class MembershipCandidate extends DataFlow::Node instanceof MembershipCandidate::Range {
|
||||||
MembershipCandidate::Range range;
|
|
||||||
|
|
||||||
MembershipCandidate() { this = range }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the expression that performs the membership test, if any.
|
* Gets the expression that performs the membership test, if any.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getTest() { result = range.getTest() }
|
DataFlow::Node getTest() { result = super.getTest() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a string that this candidate is tested against, if
|
* Gets a string that this candidate is tested against, if
|
||||||
* it can be determined.
|
* it can be determined.
|
||||||
*/
|
*/
|
||||||
string getAMemberString() { result = range.getAMemberString() }
|
string getAMemberString() { result = super.getAMemberString() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node that this candidate is tested against, if
|
* Gets a node that this candidate is tested against, if
|
||||||
* it can be determined.
|
* it can be determined.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getAMemberNode() { result = range.getAMemberNode() }
|
DataFlow::Node getAMemberNode() { result = super.getAMemberNode() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the polarity of the test.
|
* Gets the polarity of the test.
|
||||||
@@ -37,7 +34,7 @@ class MembershipCandidate extends DataFlow::Node {
|
|||||||
* If the polarity is `false` the test returns `true` if the
|
* If the polarity is `false` the test returns `true` if the
|
||||||
* collection does not contain this candidate.
|
* collection does not contain this candidate.
|
||||||
*/
|
*/
|
||||||
boolean getTestPolarity() { result = range.getTestPolarity() }
|
boolean getTestPolarity() { result = super.getTestPolarity() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,20 +8,17 @@ module StringOps {
|
|||||||
/**
|
/**
|
||||||
* A expression that is equivalent to `A.startsWith(B)` or `!A.startsWith(B)`.
|
* A expression that is equivalent to `A.startsWith(B)` or `!A.startsWith(B)`.
|
||||||
*/
|
*/
|
||||||
class StartsWith extends DataFlow::Node {
|
class StartsWith extends DataFlow::Node instanceof StartsWith::Range {
|
||||||
StartsWith::Range range;
|
|
||||||
|
|
||||||
StartsWith() { range = this }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `A` in `A.startsWith(B)`.
|
* Gets the `A` in `A.startsWith(B)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getBaseString() { result = range.getBaseString() }
|
DataFlow::Node getBaseString() { result = super.getBaseString() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `B` in `A.startsWith(B)`.
|
* Gets the `B` in `A.startsWith(B)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getSubstring() { result = range.getSubstring() }
|
DataFlow::Node getSubstring() { result = super.getSubstring() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the polarity of the check.
|
* Gets the polarity of the check.
|
||||||
@@ -29,7 +26,7 @@ module StringOps {
|
|||||||
* If the polarity is `false` the check returns `true` if the string does not start
|
* If the polarity is `false` the check returns `true` if the string does not start
|
||||||
* with the given substring.
|
* with the given substring.
|
||||||
*/
|
*/
|
||||||
boolean getPolarity() { result = range.getPolarity() }
|
boolean getPolarity() { result = super.getPolarity() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module StartsWith {
|
module StartsWith {
|
||||||
@@ -237,20 +234,17 @@ module StringOps {
|
|||||||
/**
|
/**
|
||||||
* An expression that is equivalent to `A.endsWith(B)` or `!A.endsWith(B)`.
|
* An expression that is equivalent to `A.endsWith(B)` or `!A.endsWith(B)`.
|
||||||
*/
|
*/
|
||||||
class EndsWith extends DataFlow::Node {
|
class EndsWith extends DataFlow::Node instanceof EndsWith::Range {
|
||||||
EndsWith::Range range;
|
|
||||||
|
|
||||||
EndsWith() { this = range }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `A` in `A.startsWith(B)`.
|
* Gets the `A` in `A.startsWith(B)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getBaseString() { result = range.getBaseString() }
|
DataFlow::Node getBaseString() { result = super.getBaseString() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `B` in `A.startsWith(B)`.
|
* Gets the `B` in `A.startsWith(B)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getSubstring() { result = range.getSubstring() }
|
DataFlow::Node getSubstring() { result = super.getSubstring() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the polarity if the check.
|
* Gets the polarity if the check.
|
||||||
@@ -258,7 +252,7 @@ module StringOps {
|
|||||||
* If the polarity is `false` the check returns `true` if the string does not end
|
* If the polarity is `false` the check returns `true` if the string does not end
|
||||||
* with the given substring.
|
* with the given substring.
|
||||||
*/
|
*/
|
||||||
boolean getPolarity() { result = range.getPolarity() }
|
boolean getPolarity() { result = super.getPolarity() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module EndsWith {
|
module EndsWith {
|
||||||
@@ -662,10 +656,7 @@ module StringOps {
|
|||||||
* if (!match) { ... } // <--- 'match' is the RegExpTest
|
* if (!match) { ... } // <--- 'match' is the RegExpTest
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class RegExpTest extends DataFlow::Node {
|
class RegExpTest extends DataFlow::Node instanceof RegExpTest::Range {
|
||||||
RegExpTest::Range range;
|
|
||||||
|
|
||||||
RegExpTest() { this = range }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the AST of the regular expression used in the test, if it can be seen locally.
|
* Gets the AST of the regular expression used in the test, if it can be seen locally.
|
||||||
@@ -673,7 +664,7 @@ module StringOps {
|
|||||||
RegExpTerm getRegExp() {
|
RegExpTerm getRegExp() {
|
||||||
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
|
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
|
||||||
or
|
or
|
||||||
result = range.getRegExpOperand(true).asExpr().(StringLiteral).asRegExp()
|
result = this.(RegExpTest::Range).getRegExpOperand(true).asExpr().(StringLiteral).asRegExp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -681,12 +672,12 @@ module StringOps {
|
|||||||
*
|
*
|
||||||
* In some cases this represents a string value being coerced to a RegExp object.
|
* In some cases this represents a string value being coerced to a RegExp object.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getRegExpOperand() { result = range.getRegExpOperand(_) }
|
DataFlow::Node getRegExpOperand() { result = super.getRegExpOperand(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data flow node corresponding to the string being tested against the regular expression.
|
* Gets the data flow node corresponding to the string being tested against the regular expression.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getStringOperand() { result = range.getStringOperand() }
|
DataFlow::Node getStringOperand() { result = super.getStringOperand() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the return value indicating that the string matched the regular expression.
|
* Gets the return value indicating that the string matched the regular expression.
|
||||||
@@ -694,7 +685,7 @@ module StringOps {
|
|||||||
* For example, for `regexp.exec(str) == null`, the polarity is `false`, and for
|
* For example, for `regexp.exec(str) == null`, the polarity is `false`, and for
|
||||||
* `regexp.exec(str) != null` the polarity is `true`.
|
* `regexp.exec(str) != null` the polarity is `true`.
|
||||||
*/
|
*/
|
||||||
boolean getPolarity() { result = range.getPolarity() }
|
boolean getPolarity() { result = super.getPolarity() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -701,13 +701,10 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode {
|
|||||||
* define(["fs"], function(fs) { ... }); // AMD module
|
* define(["fs"], function(fs) { ... }); // AMD module
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class ModuleImportNode extends DataFlow::SourceNode {
|
class ModuleImportNode extends DataFlow::SourceNode instanceof ModuleImportNode::Range {
|
||||||
ModuleImportNode::Range range;
|
|
||||||
|
|
||||||
ModuleImportNode() { this = range }
|
|
||||||
|
|
||||||
/** Gets the path of the imported module. */
|
/** Gets the path of the imported module. */
|
||||||
string getPath() { result = range.getPath() }
|
string getPath() { result = super.getPath() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module ModuleImportNode {
|
module ModuleImportNode {
|
||||||
@@ -843,25 +840,22 @@ module MemberKind {
|
|||||||
*
|
*
|
||||||
* Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`.
|
* Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`.
|
||||||
*/
|
*/
|
||||||
class ClassNode extends DataFlow::SourceNode {
|
class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
|
||||||
ClassNode::Range impl;
|
|
||||||
|
|
||||||
ClassNode() { this = impl }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the unqualified name of the class, if it has one or one can be determined from the context.
|
* Gets the unqualified name of the class, if it has one or one can be determined from the context.
|
||||||
*/
|
*/
|
||||||
string getName() { result = impl.getName() }
|
string getName() { result = super.getName() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a description of the class.
|
* Gets a description of the class.
|
||||||
*/
|
*/
|
||||||
string describe() { result = impl.describe() }
|
string describe() { result = super.describe() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the constructor function of this class.
|
* Gets the constructor function of this class.
|
||||||
*/
|
*/
|
||||||
FunctionNode getConstructor() { result = impl.getConstructor() }
|
FunctionNode getConstructor() { result = super.getConstructor() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an instance method declared in this class, with the given name, if any.
|
* Gets an instance method declared in this class, with the given name, if any.
|
||||||
@@ -869,7 +863,7 @@ class ClassNode extends DataFlow::SourceNode {
|
|||||||
* Does not include methods from superclasses.
|
* Does not include methods from superclasses.
|
||||||
*/
|
*/
|
||||||
FunctionNode getInstanceMethod(string name) {
|
FunctionNode getInstanceMethod(string name) {
|
||||||
result = impl.getInstanceMember(name, MemberKind::method())
|
result = super.getInstanceMember(name, MemberKind::method())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -879,7 +873,9 @@ class ClassNode extends DataFlow::SourceNode {
|
|||||||
*
|
*
|
||||||
* Does not include methods from superclasses.
|
* Does not include methods from superclasses.
|
||||||
*/
|
*/
|
||||||
FunctionNode getAnInstanceMethod() { result = impl.getAnInstanceMember(MemberKind::method()) }
|
FunctionNode getAnInstanceMethod() {
|
||||||
|
result = super.getAnInstanceMember(MemberKind::method())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the instance method, getter, or setter with the given name and kind.
|
* Gets the instance method, getter, or setter with the given name and kind.
|
||||||
@@ -887,7 +883,7 @@ class ClassNode extends DataFlow::SourceNode {
|
|||||||
* Does not include members from superclasses.
|
* Does not include members from superclasses.
|
||||||
*/
|
*/
|
||||||
FunctionNode getInstanceMember(string name, MemberKind kind) {
|
FunctionNode getInstanceMember(string name, MemberKind kind) {
|
||||||
result = impl.getInstanceMember(name, kind)
|
result = super.getInstanceMember(name, kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -895,31 +891,35 @@ class ClassNode extends DataFlow::SourceNode {
|
|||||||
*
|
*
|
||||||
* Does not include members from superclasses.
|
* Does not include members from superclasses.
|
||||||
*/
|
*/
|
||||||
FunctionNode getAnInstanceMember(MemberKind kind) { result = impl.getAnInstanceMember(kind) }
|
FunctionNode getAnInstanceMember(MemberKind kind) {
|
||||||
|
result = super.getAnInstanceMember(kind)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an instance method, getter, or setter declared in this class.
|
* Gets an instance method, getter, or setter declared in this class.
|
||||||
*
|
*
|
||||||
* Does not include members from superclasses.
|
* Does not include members from superclasses.
|
||||||
*/
|
*/
|
||||||
FunctionNode getAnInstanceMember() { result = impl.getAnInstanceMember(_) }
|
FunctionNode getAnInstanceMember() { result = super.getAnInstanceMember(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the static method declared in this class with the given name.
|
* Gets the static method declared in this class with the given name.
|
||||||
*/
|
*/
|
||||||
FunctionNode getStaticMethod(string name) { result = impl.getStaticMethod(name) }
|
FunctionNode getStaticMethod(string name) {
|
||||||
|
result = super.getStaticMethod(name)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a static method declared in this class.
|
* Gets a static method declared in this class.
|
||||||
*
|
*
|
||||||
* The constructor is not considered a static method.
|
* The constructor is not considered a static method.
|
||||||
*/
|
*/
|
||||||
FunctionNode getAStaticMethod() { result = impl.getAStaticMethod() }
|
FunctionNode getAStaticMethod() { result = super.getAStaticMethod() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a dataflow node that refers to the superclass of this class.
|
* Gets a dataflow node that refers to the superclass of this class.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getASuperClassNode() { result = impl.getASuperClassNode() }
|
DataFlow::Node getASuperClassNode() { result = super.getASuperClassNode() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a direct super class of this class.
|
* Gets a direct super class of this class.
|
||||||
@@ -1065,13 +1065,13 @@ class ClassNode extends DataFlow::SourceNode {
|
|||||||
* Gets the type annotation for the field `fieldName`, if any.
|
* Gets the type annotation for the field `fieldName`, if any.
|
||||||
*/
|
*/
|
||||||
TypeAnnotation getFieldTypeAnnotation(string fieldName) {
|
TypeAnnotation getFieldTypeAnnotation(string fieldName) {
|
||||||
result = impl.getFieldTypeAnnotation(fieldName)
|
result = super.getFieldTypeAnnotation(fieldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a decorator applied to this class.
|
* Gets a decorator applied to this class.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getADecorator() { result = impl.getADecorator() }
|
DataFlow::Node getADecorator() { result = super.getADecorator() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module ClassNode {
|
module ClassNode {
|
||||||
@@ -1357,10 +1357,7 @@ module ClassNode {
|
|||||||
* _.partial(fn, x, y, z)
|
* _.partial(fn, x, y, z)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class PartialInvokeNode extends DataFlow::Node {
|
class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range {
|
||||||
PartialInvokeNode::Range range;
|
|
||||||
|
|
||||||
PartialInvokeNode() { this = range }
|
|
||||||
|
|
||||||
/** Gets a node holding a callback invoked by this partial invocation node. */
|
/** Gets a node holding a callback invoked by this partial invocation node. */
|
||||||
DataFlow::Node getACallbackNode() {
|
DataFlow::Node getACallbackNode() {
|
||||||
@@ -1373,26 +1370,26 @@ class PartialInvokeNode extends DataFlow::Node {
|
|||||||
* Holds if `argument` is passed as argument `index` to the function in `callback`.
|
* Holds if `argument` is passed as argument `index` to the function in `callback`.
|
||||||
*/
|
*/
|
||||||
predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
||||||
range.isPartialArgument(callback, argument, index)
|
super.isPartialArgument(callback, argument, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node referring to a bound version of `callback` with `boundArgs` arguments bound.
|
* Gets a node referring to a bound version of `callback` with `boundArgs` arguments bound.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
|
DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
|
||||||
result = range.getBoundFunction(callback, boundArgs)
|
result = super.getBoundFunction(callback, boundArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node holding the receiver to be passed to the bound function, if specified.
|
* Gets the node holding the receiver to be passed to the bound function, if specified.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getBoundReceiver() { result = range.getBoundReceiver(_) }
|
DataFlow::Node getBoundReceiver() { result = super.getBoundReceiver(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node holding the receiver to be passed to the bound function, if specified.
|
* Gets the node holding the receiver to be passed to the bound function, if specified.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||||
result = range.getBoundReceiver(callback)
|
result = super.getBoundReceiver(callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ module Cheerio {
|
|||||||
* Creation of `cheerio` object, a collection of virtual DOM elements
|
* Creation of `cheerio` object, a collection of virtual DOM elements
|
||||||
* with an interface similar to that of a jQuery object.
|
* with an interface similar to that of a jQuery object.
|
||||||
*/
|
*/
|
||||||
class CheerioObjectCreation extends DataFlow::SourceNode {
|
class CheerioObjectCreation extends DataFlow::SourceNode instanceof CheerioObjectCreation::Range {
|
||||||
CheerioObjectCreation::Range range;
|
|
||||||
|
|
||||||
CheerioObjectCreation() { this = range }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module CheerioObjectCreation {
|
module CheerioObjectCreation {
|
||||||
|
|||||||
@@ -18,25 +18,22 @@ import javascript
|
|||||||
* To model additional APIs, extend `ClientRequest::Range` and implement its abstract member
|
* To model additional APIs, extend `ClientRequest::Range` and implement its abstract member
|
||||||
* predicates.
|
* predicates.
|
||||||
*/
|
*/
|
||||||
class ClientRequest extends DataFlow::InvokeNode {
|
class ClientRequest extends DataFlow::InvokeNode instanceof ClientRequest::Range {
|
||||||
ClientRequest::Range self;
|
|
||||||
|
|
||||||
ClientRequest() { this = self }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the URL of the request.
|
* Gets the URL of the request.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getUrl() { result = self.getUrl() }
|
DataFlow::Node getUrl() { result = super.getUrl() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the host of the request.
|
* Gets the host of the request.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getHost() { result = self.getHost() }
|
DataFlow::Node getHost() { result = super.getHost() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node that contributes to the data-part this request.
|
* Gets a node that contributes to the data-part this request.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getADataNode() { result = self.getADataNode() }
|
DataFlow::Node getADataNode() { result = super.getADataNode() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a data flow node that refers to some representation of the response, possibly
|
* Gets a data flow node that refers to some representation of the response, possibly
|
||||||
@@ -60,7 +57,7 @@ class ClientRequest extends DataFlow::InvokeNode {
|
|||||||
* - Any value provided by custom implementations of `ClientRequest::Range`.
|
* - Any value provided by custom implementations of `ClientRequest::Range`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
||||||
result = self.getAResponseDataNode(responseType, promise)
|
result = this.(ClientRequest::Range).getAResponseDataNode(responseType, promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +69,7 @@ class ClientRequest extends DataFlow::InvokeNode {
|
|||||||
/**
|
/**
|
||||||
* Gets a data-flow node that determines where in the file-system the result of the request should be saved.
|
* Gets a data-flow node that determines where in the file-system the result of the request should be saved.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getASavePath() { result = self.getASavePath() }
|
DataFlow::Node getASavePath() { result = super.getASavePath() }
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated class CustomClientRequest = ClientRequest::Range;
|
deprecated class CustomClientRequest = ClientRequest::Range;
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ import javascript
|
|||||||
* A call to a function that constructs a function composition `f(g(h(...)))` from a
|
* A call to a function that constructs a function composition `f(g(h(...)))` from a
|
||||||
* series functions `f, g, h, ...`.
|
* series functions `f, g, h, ...`.
|
||||||
*/
|
*/
|
||||||
class FunctionCompositionCall extends DataFlow::CallNode {
|
class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionCompositionCall::Range {
|
||||||
FunctionCompositionCall::Range range;
|
|
||||||
|
|
||||||
FunctionCompositionCall() { this = range }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `i`th function in the composition `f(g(h(...)))`, counting from left to right.
|
* Gets the `i`th function in the composition `f(g(h(...)))`, counting from left to right.
|
||||||
@@ -19,7 +16,9 @@ class FunctionCompositionCall extends DataFlow::CallNode {
|
|||||||
* Note that this is the opposite of the order in which the function are invoked,
|
* Note that this is the opposite of the order in which the function are invoked,
|
||||||
* that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`.
|
* that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOperandNode(int i) { result = range.getOperandNode(i) }
|
DataFlow::Node getOperandNode(int i) {
|
||||||
|
result = super.getOperandNode(i)
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets a node holding one of the functions to be composed. */
|
/** Gets a node holding one of the functions to be composed. */
|
||||||
final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) }
|
final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) }
|
||||||
@@ -38,7 +37,7 @@ class FunctionCompositionCall extends DataFlow::CallNode {
|
|||||||
final DataFlow::Node getAnOperandFunction() { result = getOperandFunction(_) }
|
final DataFlow::Node getAnOperandFunction() { result = getOperandFunction(_) }
|
||||||
|
|
||||||
/** Gets the number of functions being composed. */
|
/** Gets the number of functions being composed. */
|
||||||
int getNumOperand() { result = range.getNumOperand() }
|
int getNumOperand() { result = super.getNumOperand() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -181,8 +181,7 @@ module Electron {
|
|||||||
/**
|
/**
|
||||||
* A Node.js-style HTTP or HTTPS request made using an Electron module.
|
* A Node.js-style HTTP or HTTPS request made using an Electron module.
|
||||||
*/
|
*/
|
||||||
class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest {
|
class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest instanceof ElectronClientRequest::Range {
|
||||||
override ElectronClientRequest::Range self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module ElectronClientRequest {
|
module ElectronClientRequest {
|
||||||
|
|||||||
@@ -68,40 +68,40 @@ module EventEmitter {
|
|||||||
* An EventEmitter instance that implements the EventEmitter API.
|
* An EventEmitter instance that implements the EventEmitter API.
|
||||||
* Extend EventEmitter::Range to mark something as being an EventEmitter.
|
* Extend EventEmitter::Range to mark something as being an EventEmitter.
|
||||||
*/
|
*/
|
||||||
class EventEmitter extends DataFlow::Node {
|
class EventEmitter extends DataFlow::Node instanceof EventEmitter::Range {
|
||||||
EventEmitter::Range range;
|
|
||||||
|
|
||||||
EventEmitter() { this = range }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A registration of an event handler on an EventEmitter.
|
* A registration of an event handler on an EventEmitter.
|
||||||
*/
|
*/
|
||||||
class EventRegistration extends DataFlow::Node {
|
class EventRegistration extends DataFlow::Node instanceof EventRegistration::Range {
|
||||||
EventRegistration::Range range;
|
|
||||||
|
|
||||||
EventRegistration() { this = range }
|
|
||||||
|
|
||||||
/** Gets the EventEmitter that the event handler is registered on. */
|
/** Gets the EventEmitter that the event handler is registered on. */
|
||||||
final EventEmitter getEmitter() { result = range.getEmitter() }
|
final EventEmitter getEmitter() { result = super.getEmitter() }
|
||||||
|
|
||||||
/** Gets the name of the channel if possible. */
|
/** Gets the name of the channel if possible. */
|
||||||
string getChannel() { result = range.getChannel() }
|
string getChannel() { result = super.getChannel() }
|
||||||
|
|
||||||
/** Gets the `i`th parameter in the event handler. */
|
/** Gets the `i`th parameter in the event handler. */
|
||||||
DataFlow::Node getReceivedItem(int i) { result = range.getReceivedItem(i) }
|
DataFlow::Node getReceivedItem(int i) {
|
||||||
|
result = super.getReceivedItem(i)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a value that is returned by the event handler.
|
* Gets a value that is returned by the event handler.
|
||||||
* The default implementation is that no value can be returned.
|
* The default implementation is that no value can be returned.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getAReturnedValue() { result = range.getAReturnedValue() }
|
DataFlow::Node getAReturnedValue() {
|
||||||
|
result = super.getAReturnedValue()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a dispatch that this event handler can return a value to.
|
* Get a dispatch that this event handler can return a value to.
|
||||||
* The default implementation is that there exists no such dispatch.
|
* The default implementation is that there exists no such dispatch.
|
||||||
*/
|
*/
|
||||||
EventDispatch getAReturnDispatch() { result = range.getAReturnDispatch() }
|
EventDispatch getAReturnDispatch() {
|
||||||
|
result = super.getAReturnDispatch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module EventRegistration {
|
module EventRegistration {
|
||||||
@@ -140,26 +140,23 @@ module EventRegistration {
|
|||||||
/**
|
/**
|
||||||
* A dispatch of an event on an EventEmitter.
|
* A dispatch of an event on an EventEmitter.
|
||||||
*/
|
*/
|
||||||
class EventDispatch extends DataFlow::Node {
|
class EventDispatch extends DataFlow::Node instanceof EventDispatch::Range {
|
||||||
EventDispatch::Range range;
|
|
||||||
|
|
||||||
EventDispatch() { this = range }
|
|
||||||
|
|
||||||
/** Gets the emitter that the event dispatch happens on. */
|
/** Gets the emitter that the event dispatch happens on. */
|
||||||
EventEmitter getEmitter() { result = range.getEmitter() }
|
EventEmitter getEmitter() { result = super.getEmitter() }
|
||||||
|
|
||||||
/** Gets the name of the channel if possible. */
|
/** Gets the name of the channel if possible. */
|
||||||
string getChannel() { result = range.getChannel() }
|
string getChannel() { result = this.(EventDispatch::Range).getChannel() }
|
||||||
|
|
||||||
/** Gets the `i`th argument that is send to the event handler. */
|
/** Gets the `i`th argument that is send to the event handler. */
|
||||||
DataFlow::Node getSentItem(int i) { result = range.getSentItem(i) }
|
DataFlow::Node getSentItem(int i) { result = super.getSentItem(i) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an EventRegistration that this event dispatch can send an event to.
|
* Get an EventRegistration that this event dispatch can send an event to.
|
||||||
* The default implementation is that the emitters of the dispatch and registration have to be equal.
|
* The default implementation is that the emitters of the dispatch and registration have to be equal.
|
||||||
* Channels are by default ignored.
|
* Channels are by default ignored.
|
||||||
*/
|
*/
|
||||||
EventRegistration getAReceiver() { result = range.getAReceiver() }
|
EventRegistration getAReceiver() { result = super.getAReceiver() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module EventDispatch {
|
module EventDispatch {
|
||||||
|
|||||||
@@ -540,16 +540,13 @@ module HTTP {
|
|||||||
/**
|
/**
|
||||||
* An object that contains one or more potential route handlers.
|
* An object that contains one or more potential route handlers.
|
||||||
*/
|
*/
|
||||||
class RouteHandlerCandidateContainer extends DataFlow::Node {
|
class RouteHandlerCandidateContainer extends DataFlow::Node instanceof RouteHandlerCandidateContainer::Range {
|
||||||
RouteHandlerCandidateContainer::Range self;
|
|
||||||
|
|
||||||
RouteHandlerCandidateContainer() { this = self }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the route handler in this container that is accessed at `access`.
|
* Gets the route handler in this container that is accessed at `access`.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
||||||
result = self.getRouteHandler(access)
|
result = super.getRouteHandler(access)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -831,8 +831,7 @@ module NodeJSLib {
|
|||||||
* A data flow node that is an HTTP or HTTPS client request made by a Node.js application,
|
* A data flow node that is an HTTP or HTTPS client request made by a Node.js application,
|
||||||
* for example `http.request(url)`.
|
* for example `http.request(url)`.
|
||||||
*/
|
*/
|
||||||
class NodeJSClientRequest extends ClientRequest {
|
class NodeJSClientRequest extends ClientRequest instanceof NodeJSClientRequest::Range {
|
||||||
override NodeJSClientRequest::Range self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module NodeJSClientRequest {
|
module NodeJSClientRequest {
|
||||||
|
|||||||
@@ -14,20 +14,17 @@ import javascript
|
|||||||
* To model additional APIs, extend `PropertyProjection::Range` and implement its abstract member
|
* To model additional APIs, extend `PropertyProjection::Range` and implement its abstract member
|
||||||
* predicates.
|
* predicates.
|
||||||
*/
|
*/
|
||||||
class PropertyProjection extends DataFlow::CallNode {
|
class PropertyProjection extends DataFlow::CallNode instanceof PropertyProjection::Range {
|
||||||
PropertyProjection::Range self;
|
|
||||||
|
|
||||||
PropertyProjection() { this = self }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the argument for the object to project properties from, such as `o` in `_.get(o, 'a.b')`.
|
* Gets the argument for the object to project properties from, such as `o` in `_.get(o, 'a.b')`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getObject() { result = self.getObject() }
|
DataFlow::Node getObject() { result = super.getObject() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an argument that selects the properties to project, such as `'a.b'` in `_.get(o, 'a.b')`.
|
* Gets an argument that selects the properties to project, such as `'a.b'` in `_.get(o, 'a.b')`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getASelector() { result = self.getASelector() }
|
DataFlow::Node getASelector() { result = super.getASelector() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this call returns the value of a single projected property, as opposed to an object that can contain multiple projected properties.
|
* Holds if this call returns the value of a single projected property, as opposed to an object that can contain multiple projected properties.
|
||||||
@@ -36,7 +33,7 @@ class PropertyProjection extends DataFlow::CallNode {
|
|||||||
* - This predicate holds for `_.get({a: 'b'}, 'a')`, which returns `'b'`,
|
* - This predicate holds for `_.get({a: 'b'}, 'a')`, which returns `'b'`,
|
||||||
* - This predicate does not hold for `_.pick({a: 'b', c: 'd'}}, 'a')`, which returns `{a: 'b'}`,
|
* - This predicate does not hold for `_.pick({a: 'b', c: 'd'}}, 'a')`, which returns `{a: 'b'}`,
|
||||||
*/
|
*/
|
||||||
predicate isSingletonProjection() { self.isSingletonProjection() }
|
predicate isSingletonProjection() { super.isSingletonProjection() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module PropertyProjection {
|
module PropertyProjection {
|
||||||
|
|||||||
@@ -56,10 +56,7 @@ module Redux {
|
|||||||
/**
|
/**
|
||||||
* Creation of a redux store, usually via a call to `createStore`.
|
* Creation of a redux store, usually via a call to `createStore`.
|
||||||
*/
|
*/
|
||||||
class StoreCreation extends DataFlow::SourceNode {
|
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
|
||||||
StoreCreation::Range range;
|
|
||||||
|
|
||||||
StoreCreation() { this = range }
|
|
||||||
|
|
||||||
/** Gets a reference to the store. */
|
/** Gets a reference to the store. */
|
||||||
DataFlow::SourceNode ref() { result = asApiNode().getAUse() }
|
DataFlow::SourceNode ref() { result = asApiNode().getAUse() }
|
||||||
@@ -68,7 +65,7 @@ module Redux {
|
|||||||
API::Node asApiNode() { result.getAnImmediateUse() = this }
|
API::Node asApiNode() { result.getAnImmediateUse() = this }
|
||||||
|
|
||||||
/** Gets the data flow node holding the root reducer for this store. */
|
/** Gets the data flow node holding the root reducer for this store. */
|
||||||
DataFlow::Node getReducerArg() { result = range.getReducerArg() }
|
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
|
||||||
|
|
||||||
/** Gets a data flow node referring to the root reducer. */
|
/** Gets a data flow node referring to the root reducer. */
|
||||||
DataFlow::SourceNode getAReducerSource() { result = getReducerArg().(ReducerArg).getASource() }
|
DataFlow::SourceNode getAReducerSource() { result = getReducerArg().(ReducerArg).getASource() }
|
||||||
@@ -423,13 +420,10 @@ module Redux {
|
|||||||
* Some action creators dispatch the action to a store, while for others, the value is returned and it is simply assumed to be dispatched
|
* Some action creators dispatch the action to a store, while for others, the value is returned and it is simply assumed to be dispatched
|
||||||
* at some point. We model all action creators as if they dispatch the action they create.
|
* at some point. We model all action creators as if they dispatch the action they create.
|
||||||
*/
|
*/
|
||||||
class ActionCreator extends DataFlow::SourceNode {
|
class ActionCreator extends DataFlow::SourceNode instanceof ActionCreator::Range {
|
||||||
ActionCreator::Range range;
|
|
||||||
|
|
||||||
ActionCreator() { this = range }
|
|
||||||
|
|
||||||
/** Gets the `type` property of actions created by this action creator, if it is known. */
|
/** Gets the `type` property of actions created by this action creator, if it is known. */
|
||||||
string getTypeTag() { result = range.getTypeTag() }
|
string getTypeTag() { result = super.getTypeTag() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the middleware function that transforms arguments passed to this function into the
|
* Gets the middleware function that transforms arguments passed to this function into the
|
||||||
@@ -442,7 +436,7 @@ module Redux {
|
|||||||
* the action payload. Otherwise, the return value is the payload itself.
|
* the action payload. Otherwise, the return value is the payload itself.
|
||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
||||||
result = range.getMiddlewareFunction(async)
|
result = super.getMiddlewareFunction(async)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a data flow node referring to this action creator. */
|
/** Gets a data flow node referring to this action creator. */
|
||||||
|
|||||||
@@ -14,13 +14,10 @@ module ShellJS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A member of the `shelljs` library. */
|
/** A member of the `shelljs` library. */
|
||||||
class Member extends DataFlow::SourceNode {
|
class Member extends DataFlow::SourceNode instanceof Member::Range {
|
||||||
Member::Range range;
|
|
||||||
|
|
||||||
Member() { this = range }
|
|
||||||
|
|
||||||
/** Gets the name of `shelljs` member being referenced, such as `cat` in `shelljs.cat`. */
|
/** Gets the name of `shelljs` member being referenced, such as `cat` in `shelljs.cat`. */
|
||||||
string getName() { result = range.getName() }
|
string getName() { result = super.getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module Member {
|
module Member {
|
||||||
|
|||||||
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
|
|||||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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`.
|
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||||
*/
|
*/
|
||||||
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||||
(
|
simpleLocalFlowStepExt(node1, node2) and
|
||||||
simpleLocalFlowStep(node1, node2) or
|
|
||||||
reverseStepThroughInputOutputAlias(node1, node2)
|
|
||||||
) and
|
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, 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.
|
* 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) {
|
private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||||
jumpStep(node1, node2) and
|
jumpStepCached(node1, node2) and
|
||||||
not outBarrier(node1, config) and
|
not outBarrier(node1, config) and
|
||||||
not inBarrier(node2, config) and
|
not inBarrier(node2, config) and
|
||||||
not fullBarrier(node1, config) and
|
not fullBarrier(node1, config) and
|
||||||
@@ -388,7 +385,7 @@ private module Stage1 {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
fwdFlow(arg, cc, config) and
|
fwdFlow(arg, cc, config) and
|
||||||
viableParamArg(call, _, arg)
|
viableParamArg(call, _, arg)
|
||||||
)
|
)
|
||||||
@@ -515,24 +512,22 @@ private module Stage1 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate viableParamArgNodeCandFwd1(
|
predicate viableParamArgNodeCandFwd1(
|
||||||
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
|
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
|
||||||
) {
|
) {
|
||||||
viableParamArg(call, p, arg) and
|
viableParamArg(call, p, arg) and
|
||||||
fwdFlow(arg, config)
|
fwdFlow(arg, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
|
exists(ParamNode p |
|
||||||
) {
|
|
||||||
exists(ParameterNode p |
|
|
||||||
revFlow(p, toReturn, config) and
|
revFlow(p, toReturn, config) and
|
||||||
viableParamArgNodeCandFwd1(call, p, arg, config)
|
viableParamArgNodeCandFwd1(call, p, arg, config)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
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)
|
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
|
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||||
* candidate for the origin of a summary.
|
* 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 |
|
exists(ReturnKindExt kind |
|
||||||
throughFlowNodeCand(p, config) and
|
throughFlowNodeCand(p, config) and
|
||||||
returnFlowCallableNodeCand(c, kind, config) and
|
returnFlowCallableNodeCand(c, kind, config) and
|
||||||
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate viableParamArgNodeCand1(
|
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::viableParamArgNodeCandFwd1(call, p, arg, config) and
|
||||||
Stage1::revFlow(arg, config)
|
Stage1::revFlow(arg, config)
|
||||||
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
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
|
viableParamArgNodeCand1(call, p, arg, config) and
|
||||||
Stage1::revFlow(p, config) and
|
Stage1::revFlow(p, config) and
|
||||||
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand1(
|
private predicate flowIntoCallNodeCand1(
|
||||||
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, arg, p, config) and
|
flowIntoCallNodeCand1(call, arg, p, config) and
|
||||||
exists(int b, int j |
|
exists(int b, int j |
|
||||||
@@ -944,10 +938,10 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -992,7 +986,7 @@ private module Stage2 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||||
)
|
)
|
||||||
@@ -1133,10 +1127,9 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1146,7 +1139,7 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1199,13 +1192,13 @@ private module Stage2 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCallNodeCand2(
|
private predicate flowIntoCallNodeCand2(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
|
||||||
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
|
|||||||
*/
|
*/
|
||||||
private class FlowCheckNode extends Node {
|
private class FlowCheckNode extends Node {
|
||||||
FlowCheckNode() {
|
FlowCheckNode() {
|
||||||
this instanceof CastNode or
|
castNode(this) or
|
||||||
clearsContent(this, _)
|
clearsContentCached(this, _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
|
|||||||
config.isSource(node) or
|
config.isSource(node) or
|
||||||
jumpStep(_, node, config) or
|
jumpStep(_, node, config) or
|
||||||
additionalJumpStep(_, node, config) or
|
additionalJumpStep(_, node, config) or
|
||||||
node instanceof ParameterNode or
|
node instanceof ParamNode or
|
||||||
node instanceof OutNodeExt or
|
node instanceof OutNodeExt or
|
||||||
store(_, _, node, _) or
|
store(_, _, node, _) or
|
||||||
read(_, _, node) or
|
read(_, _, node) or
|
||||||
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
|
|||||||
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
|
||||||
LocalCallContext cc
|
LocalCallContext cc
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
localFlowEntry(node1, pragma[only_bind_into](config)) and
|
||||||
(
|
(
|
||||||
localFlowStepNodeCand1(node1, node2, config) and
|
localFlowStepNodeCand1(node1, node2, config) and
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = getNodeType(node1)
|
t = getNodeDataFlowType(node1)
|
||||||
or
|
or
|
||||||
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
additionalLocalFlowStepNodeCand2(node1, node2, config) and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2)
|
t = getNodeDataFlowType(node2)
|
||||||
) and
|
) and
|
||||||
node1 != node2 and
|
node1 != node2 and
|
||||||
cc.relevantFor(getNodeEnclosingCallable(node1)) 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))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
or
|
or
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
|
|||||||
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
additionalLocalFlowStepNodeCand2(mid, node2, config) and
|
||||||
not mid instanceof FlowCheckNode and
|
not mid instanceof FlowCheckNode and
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node2) and
|
t = getNodeDataFlowType(node2) and
|
||||||
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
Stage2::revFlow(node2, pragma[only_bind_into](config))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1384,7 +1376,7 @@ private module Stage3 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -1443,7 +1435,9 @@ private module Stage3 {
|
|||||||
bindingset[node, ap]
|
bindingset[node, ap]
|
||||||
private predicate filter(Node node, Ap ap) {
|
private predicate filter(Node node, Ap ap) {
|
||||||
not ap.isClearedAt(node) and
|
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]
|
bindingset[ap, contentType]
|
||||||
@@ -1583,10 +1577,10 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -1631,7 +1625,7 @@ private module Stage3 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -1772,10 +1766,9 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -1785,7 +1778,7 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -1838,13 +1831,13 @@ private module Stage3 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2088,7 +2081,7 @@ private module Stage4 {
|
|||||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||||
|
|
||||||
private ApNil getApNil(Node node) {
|
private ApNil getApNil(Node node) {
|
||||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[tc, tail]
|
bindingset[tc, tail]
|
||||||
@@ -2155,8 +2148,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate flowIntoCall(
|
private predicate flowIntoCall(
|
||||||
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
|
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
|
||||||
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
|
||||||
@@ -2300,10 +2292,10 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fwdFlowIn(
|
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
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
exists(ArgNode arg, boolean allowsFieldFlow |
|
||||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||||
@@ -2348,7 +2340,7 @@ private module Stage4 {
|
|||||||
private predicate fwdFlowIsEntered(
|
private predicate fwdFlowIsEntered(
|
||||||
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||||
)
|
)
|
||||||
@@ -2489,10 +2481,9 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowIn(
|
private predicate revFlowIn(
|
||||||
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
|
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||||
Configuration config
|
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p, boolean allowsFieldFlow |
|
exists(ParamNode p, boolean allowsFieldFlow |
|
||||||
revFlow(p, toReturn, returnAp, ap, config) and
|
revFlow(p, toReturn, returnAp, ap, config) and
|
||||||
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||||
|
|
|
|
||||||
@@ -2502,7 +2493,7 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revFlowInToReturn(
|
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)
|
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
|
||||||
}
|
}
|
||||||
@@ -2555,13 +2546,13 @@ private module Stage4 {
|
|||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate parameterFlow(
|
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
|
revFlow(p, true, apSome(ap0), ap, config) and
|
||||||
c = getNodeEnclosingCallable(p)
|
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 |
|
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||||
parameterFlow(p, ap, ap0, c, config) and
|
parameterFlow(p, ap, ap0, c, config) and
|
||||||
c = getNodeEnclosingCallable(ret) and
|
c = getNodeEnclosingCallable(ret) and
|
||||||
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
|||||||
|
|
||||||
private newtype TSummaryCtx =
|
private newtype TSummaryCtx =
|
||||||
TSummaryCtxNone() or
|
TSummaryCtxNone() or
|
||||||
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
|
TSummaryCtxSome(ParamNode p, AccessPath ap) {
|
||||||
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
|
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. */
|
/** A summary context from which a flow summary can be generated. */
|
||||||
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||||
private ParameterNode p;
|
private ParamNode p;
|
||||||
private AccessPath ap;
|
private AccessPath ap;
|
||||||
|
|
||||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||||
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
|
|||||||
config.isSource(node) and
|
config.isSource(node) and
|
||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// ... or a step from an existing PathNode to another node.
|
// ... or a step from an existing PathNode to another node.
|
||||||
exists(PathNodeMid mid |
|
exists(PathNodeMid mid |
|
||||||
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
|
|||||||
Configuration getConfiguration() { none() }
|
Configuration getConfiguration() { none() }
|
||||||
|
|
||||||
private predicate isHidden() {
|
private predicate isHidden() {
|
||||||
nodeIsHidden(this.getNode()) and
|
hiddenNode(this.getNode()) and
|
||||||
not this.isSource() and
|
not this.isSource() and
|
||||||
not this instanceof PathNodeSink
|
not this instanceof PathNodeSink
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc instanceof SummaryCtxNone and
|
sc instanceof SummaryCtxNone and
|
||||||
mid.getAp() instanceof AccessPathNil and
|
mid.getAp() instanceof AccessPathNil and
|
||||||
ap = TAccessPathNil(getNodeType(node))
|
ap = TAccessPathNil(getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
|
||||||
sc = mid.getSummaryCtx()
|
sc = mid.getSummaryCtx()
|
||||||
@@ -3235,7 +3226,7 @@ pragma[noinline]
|
|||||||
private predicate pathIntoArg(
|
private predicate pathIntoArg(
|
||||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3248,7 +3239,7 @@ pragma[noinline]
|
|||||||
private predicate parameterCand(
|
private predicate parameterCand(
|
||||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
Stage4::revFlow(p, _, _, apa, config) and
|
Stage4::revFlow(p, _, _, apa, config) and
|
||||||
p.isParameterOf(callable, i)
|
p.isParameterOf(callable, i)
|
||||||
)
|
)
|
||||||
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
|
|||||||
* respectively.
|
* respectively.
|
||||||
*/
|
*/
|
||||||
private predicate pathIntoCallable(
|
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
|
DataFlowCall call
|
||||||
) {
|
) {
|
||||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||||
@@ -3568,7 +3559,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
private newtype TSummaryCtx1 =
|
private newtype TSummaryCtx1 =
|
||||||
TSummaryCtx1None() or
|
TSummaryCtx1None() or
|
||||||
TSummaryCtx1Param(ParameterNode p)
|
TSummaryCtx1Param(ParamNode p)
|
||||||
|
|
||||||
private newtype TSummaryCtx2 =
|
private newtype TSummaryCtx2 =
|
||||||
TSummaryCtx2None() or
|
TSummaryCtx2None() or
|
||||||
@@ -3591,7 +3582,7 @@ private module FlowExploration {
|
|||||||
cc instanceof CallContextAny and
|
cc instanceof CallContextAny and
|
||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
not fullBarrier(node, config) and
|
not fullBarrier(node, config) and
|
||||||
exists(config.explorationLimit())
|
exists(config.explorationLimit())
|
||||||
or
|
or
|
||||||
@@ -3611,7 +3602,7 @@ private module FlowExploration {
|
|||||||
or
|
or
|
||||||
exists(PartialPathNodeRev mid |
|
exists(PartialPathNodeRev mid |
|
||||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
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
|
not fullBarrier(node, config) and
|
||||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||||
)
|
)
|
||||||
@@ -3625,9 +3616,9 @@ private module FlowExploration {
|
|||||||
exists(PartialPathNodeFwd mid |
|
exists(PartialPathNodeFwd mid |
|
||||||
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
|
||||||
not fullBarrier(node, 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
|
if node instanceof CastingNode
|
||||||
then compatibleTypes(getNodeType(node), ap.getType())
|
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
|
||||||
else any()
|
else any()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3774,7 @@ private module FlowExploration {
|
|||||||
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
|
||||||
PartialAccessPath ap, Configuration config
|
PartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
|
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
|
||||||
(
|
(
|
||||||
localFlowStep(mid.getNode(), node, config) and
|
localFlowStep(mid.getNode(), node, config) and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
@@ -3797,7 +3788,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -3813,7 +3804,7 @@ private module FlowExploration {
|
|||||||
sc1 = TSummaryCtx1None() and
|
sc1 = TSummaryCtx1None() and
|
||||||
sc2 = TSummaryCtx2None() and
|
sc2 = TSummaryCtx2None() and
|
||||||
mid.getAp() instanceof PartialAccessPathNil and
|
mid.getAp() instanceof PartialAccessPathNil and
|
||||||
ap = TPartialNil(getNodeType(node)) and
|
ap = TPartialNil(getNodeDataFlowType(node)) and
|
||||||
config = mid.getConfiguration()
|
config = mid.getConfiguration()
|
||||||
or
|
or
|
||||||
partialPathStoreStep(mid, _, _, node, ap) and
|
partialPathStoreStep(mid, _, _, node, ap) and
|
||||||
@@ -3827,7 +3818,7 @@ private module FlowExploration {
|
|||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
sc2 = mid.getSummaryCtx2() and
|
sc2 = mid.getSummaryCtx2() and
|
||||||
apConsFwd(ap, tc, ap0, config) and
|
apConsFwd(ap, tc, ap0, config) and
|
||||||
compatibleTypes(ap.getType(), getNodeType(node))
|
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
|
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,
|
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
arg = mid.getNode() and
|
arg = mid.getNode() and
|
||||||
cc = mid.getCallContext() and
|
cc = mid.getCallContext() and
|
||||||
arg.argumentOf(call, i) and
|
arg.argumentOf(call, i) and
|
||||||
@@ -3943,7 +3934,7 @@ private module FlowExploration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private predicate partialPathIntoCallable(
|
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,
|
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
@@ -3980,7 +3971,7 @@ private module FlowExploration {
|
|||||||
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
|
||||||
PartialAccessPath ap, Configuration config
|
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
|
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
|
||||||
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
|
||||||
)
|
)
|
||||||
@@ -4037,7 +4028,7 @@ private module FlowExploration {
|
|||||||
apConsRev(ap, c, ap0, config)
|
apConsRev(ap, c, ap0, config)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(ParameterNode p |
|
exists(ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
viableParamArg(_, p, node) and
|
viableParamArg(_, p, node) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4115,7 +4106,7 @@ private module FlowExploration {
|
|||||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||||
Configuration config
|
Configuration config
|
||||||
) {
|
) {
|
||||||
exists(PartialPathNodeRev mid, ParameterNode p |
|
exists(PartialPathNodeRev mid, ParamNode p |
|
||||||
mid.getNode() = p and
|
mid.getNode() = p and
|
||||||
p.isParameterOf(_, pos) and
|
p.isParameterOf(_, pos) and
|
||||||
sc1 = mid.getSummaryCtx1() and
|
sc1 = mid.getSummaryCtx1() and
|
||||||
@@ -4138,7 +4129,7 @@ private module FlowExploration {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate revPartialPathThroughCallable(
|
private predicate revPartialPathThroughCallable(
|
||||||
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
|
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
|
||||||
) {
|
) {
|
||||||
exists(DataFlowCall call, int pos |
|
exists(DataFlowCall call, int pos |
|
||||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
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.
|
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||||
*/
|
*/
|
||||||
private module LambdaFlow {
|
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)
|
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)
|
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 |
|
exists(int i |
|
||||||
viableParamNonLambda(call, i, p) and
|
viableParamNonLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
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 |
|
exists(int i |
|
||||||
viableParamLambda(call, i, p) and
|
viableParamLambda(call, i, p) and
|
||||||
arg.argumentOf(call, i)
|
arg.argumentOf(call, i)
|
||||||
@@ -118,8 +118,8 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
|
||||||
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
|
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
|
||||||
then compatibleTypes(t, getNodeType(node))
|
then compatibleTypes(t, getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ private module LambdaFlow {
|
|||||||
boolean toJump, DataFlowCallOption lastCall
|
boolean toJump, DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
lambdaCall(lambdaCall, kind, node) and
|
lambdaCall(lambdaCall, kind, node) and
|
||||||
t = getNodeType(node) and
|
t = getNodeDataFlowType(node) and
|
||||||
toReturn = false and
|
toReturn = false and
|
||||||
toJump = false and
|
toJump = false and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
@@ -146,7 +146,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -160,7 +160,7 @@ private module LambdaFlow {
|
|||||||
toJump = true and
|
toJump = true and
|
||||||
lastCall = TDataFlowCallNone()
|
lastCall = TDataFlowCallNone()
|
||||||
|
|
|
|
||||||
jumpStep(node, mid) and
|
jumpStepCached(node, mid) and
|
||||||
t = t0
|
t = t0
|
||||||
or
|
or
|
||||||
exists(boolean preservesValue |
|
exists(boolean preservesValue |
|
||||||
@@ -168,7 +168,7 @@ private module LambdaFlow {
|
|||||||
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
||||||
|
|
|
|
||||||
preservesValue = false and
|
preservesValue = false and
|
||||||
t = getNodeType(node)
|
t = getNodeDataFlowType(node)
|
||||||
or
|
or
|
||||||
preservesValue = true and
|
preservesValue = true and
|
||||||
t = t0
|
t = t0
|
||||||
@@ -176,7 +176,7 @@ private module LambdaFlow {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow into a callable
|
// 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
|
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
|
||||||
(
|
(
|
||||||
if lastCall0 = TDataFlowCallNone() and toJump = false
|
if lastCall0 = TDataFlowCallNone() and toJump = false
|
||||||
@@ -227,7 +227,7 @@ private module LambdaFlow {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate revLambdaFlowIn(
|
predicate revLambdaFlowIn(
|
||||||
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
|
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
|
||||||
DataFlowCallOption lastCall
|
DataFlowCallOption lastCall
|
||||||
) {
|
) {
|
||||||
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
|
||||||
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private module 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`.
|
* 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`.
|
* The instance parameter is considered to have index `-1`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
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)
|
p.isParameterOf(viableCallableExt(call), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +353,11 @@ private module Cached {
|
|||||||
* dispatch into account.
|
* dispatch into account.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
|
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
viableParam(call, i, p) and
|
viableParam(call, i, p) and
|
||||||
arg.argumentOf(call, i) 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`.
|
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
|
||||||
p = node and
|
p = node and
|
||||||
read = false
|
read = false
|
||||||
or
|
or
|
||||||
@@ -325,30 +408,30 @@ private module Cached {
|
|||||||
// read
|
// read
|
||||||
exists(Node mid |
|
exists(Node mid |
|
||||||
parameterValueFlowCand(p, mid, false) and
|
parameterValueFlowCand(p, mid, false) and
|
||||||
readStep(mid, _, node) and
|
read(mid, _, node) and
|
||||||
read = true
|
read = true
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no prior read
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, false) and
|
parameterValueFlowArgCand(p, arg, false) and
|
||||||
argumentValueFlowsThroughCand(arg, node, read)
|
argumentValueFlowsThroughCand(arg, node, read)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArgCand(p, arg, read) and
|
parameterValueFlowArgCand(p, arg, read) and
|
||||||
argumentValueFlowsThroughCand(arg, node, false)
|
argumentValueFlowsThroughCand(arg, node, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
|
||||||
parameterValueFlowCand(p, arg, read)
|
parameterValueFlowCand(p, arg, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
|
||||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
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
|
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||||
* node.
|
* node.
|
||||||
*/
|
*/
|
||||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlowCand(p, ret, read) and
|
parameterValueFlowCand(p, ret, read) and
|
||||||
kind = ret.getKind()
|
kind = ret.getKind()
|
||||||
@@ -369,9 +452,9 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThroughCand0(
|
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)
|
parameterValueFlowReturnCand(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -382,14 +465,14 @@ private module Cached {
|
|||||||
*
|
*
|
||||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
* `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 |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate cand(ParameterNode p, Node n) {
|
predicate cand(ParamNode p, Node n) {
|
||||||
parameterValueFlowCand(p, n, _) and
|
parameterValueFlowCand(p, n, _) and
|
||||||
(
|
(
|
||||||
parameterValueFlowReturnCand(p, _, _)
|
parameterValueFlowReturnCand(p, _, _)
|
||||||
@@ -416,21 +499,21 @@ private module Cached {
|
|||||||
* If a read step was taken, then `read` captures the `Content`, the
|
* If a read step was taken, then `read` captures the `Content`, the
|
||||||
* container type, and the content type.
|
* 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
|
parameterValueFlow0(p, node, read) and
|
||||||
if node instanceof CastingNode
|
if node instanceof CastingNode
|
||||||
then
|
then
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(p), getNodeType(node))
|
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(read.getContentType(), getNodeType(node))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
|
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
|
||||||
p = node and
|
p = node and
|
||||||
Cand::cand(p, _) and
|
Cand::cand(p, _) and
|
||||||
read = TReadStepTypesNone()
|
read = TReadStepTypesNone()
|
||||||
@@ -447,7 +530,7 @@ private module Cached {
|
|||||||
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
|
||||||
read.getContentType()) and
|
read.getContentType()) and
|
||||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||||
compatibleTypes(getNodeType(p), read.getContainerType())
|
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
|
||||||
@@ -455,34 +538,32 @@ private module Cached {
|
|||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlow0_0(
|
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
|
// flow through: no prior read
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, mustBeNone) and
|
parameterValueFlowArg(p, arg, mustBeNone) and
|
||||||
argumentValueFlowsThrough(arg, read, node)
|
argumentValueFlowsThrough(arg, read, node)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// flow through: no read inside method
|
// flow through: no read inside method
|
||||||
exists(ArgumentNode arg |
|
exists(ArgNode arg |
|
||||||
parameterValueFlowArg(p, arg, read) and
|
parameterValueFlowArg(p, arg, read) and
|
||||||
argumentValueFlowsThrough(arg, mustBeNone, node)
|
argumentValueFlowsThrough(arg, mustBeNone, node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate parameterValueFlowArg(
|
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
|
||||||
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
|
|
||||||
) {
|
|
||||||
parameterValueFlow(p, arg, read) and
|
parameterValueFlow(p, arg, read) and
|
||||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate argumentValueFlowsThrough0(
|
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)
|
parameterValueFlowReturn(param, kind, read)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -496,18 +577,18 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
|
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
|
||||||
exists(DataFlowCall call, ReturnKind kind |
|
exists(DataFlowCall call, ReturnKind kind |
|
||||||
argumentValueFlowsThrough0(call, arg, kind, read) and
|
argumentValueFlowsThrough0(call, arg, kind, read) and
|
||||||
out = getAnOutNode(call, kind)
|
out = getAnOutNode(call, kind)
|
||||||
|
|
|
|
||||||
// normal flow through
|
// normal flow through
|
||||||
read = TReadStepTypesNone() and
|
read = TReadStepTypesNone() and
|
||||||
compatibleTypes(getNodeType(arg), getNodeType(out))
|
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
|
||||||
or
|
or
|
||||||
// getter
|
// getter
|
||||||
compatibleTypes(getNodeType(arg), read.getContainerType()) and
|
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
|
||||||
compatibleTypes(read.getContentType(), getNodeType(out))
|
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +597,7 @@ private module Cached {
|
|||||||
* value-preserving steps and a single read step, not taking call
|
* value-preserving steps and a single read step, not taking call
|
||||||
* contexts into account, thus representing a getter-step.
|
* 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)
|
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +610,7 @@ private module Cached {
|
|||||||
* container type, and the content type.
|
* container type, and the content type.
|
||||||
*/
|
*/
|
||||||
private predicate parameterValueFlowReturn(
|
private predicate parameterValueFlowReturn(
|
||||||
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
|
ParamNode p, ReturnKind kind, ReadStepTypesOption read
|
||||||
) {
|
) {
|
||||||
exists(ReturnNode ret |
|
exists(ReturnNode ret |
|
||||||
parameterValueFlow(p, ret, read) and
|
parameterValueFlow(p, ret, read) and
|
||||||
@@ -553,7 +634,7 @@ private module Cached {
|
|||||||
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
|
||||||
mayBenefitFromCallContext(call, callable)
|
mayBenefitFromCallContext(call, callable)
|
||||||
or
|
or
|
||||||
callable = call.getEnclosingCallable() and
|
callEnclosingCallable(call, callable) and
|
||||||
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +692,7 @@ private module Cached {
|
|||||||
mayBenefitFromCallContextExt(call, _) and
|
mayBenefitFromCallContextExt(call, _) and
|
||||||
c = viableCallableExt(call) and
|
c = viableCallableExt(call) and
|
||||||
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) 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
|
ctxtgts < tgts
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -635,8 +716,7 @@ private module Cached {
|
|||||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
* 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.
|
* node `n`, in the same callable, using only value-preserving steps.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
|
||||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
|
||||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,9 +724,9 @@ private module Cached {
|
|||||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||||
) {
|
) {
|
||||||
storeStep(node1, c, node2) and
|
storeStep(node1, c, node2) and
|
||||||
readStep(_, c, _) and
|
read(_, c, _) and
|
||||||
contentType = getNodeType(node1) and
|
contentType = getNodeDataFlowType(node1) and
|
||||||
containerType = getNodeType(node2)
|
containerType = getNodeDataFlowType(node2)
|
||||||
or
|
or
|
||||||
exists(Node n1, Node n2 |
|
exists(Node n1, Node n2 |
|
||||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||||
@@ -654,12 +734,15 @@ private module Cached {
|
|||||||
|
|
|
|
||||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||||
or
|
or
|
||||||
readStep(n2, c, n1) and
|
read(n2, c, n1) and
|
||||||
contentType = getNodeType(n1) and
|
contentType = getNodeDataFlowType(n1) and
|
||||||
containerType = getNodeType(n2)
|
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
|
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||||
* `f`.
|
* `f`.
|
||||||
@@ -678,8 +761,9 @@ private module Cached {
|
|||||||
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
* are aliases. A typical example is a function returning `this`, implementing a fluent
|
||||||
* interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
cached
|
private predicate reverseStepThroughInputOutputAlias(
|
||||||
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
|
PostUpdateNode fromNode, PostUpdateNode toNode
|
||||||
|
) {
|
||||||
exists(Node fromPre, Node toPre |
|
exists(Node fromPre, Node toPre |
|
||||||
fromPre = fromNode.getPreUpdateNode() and
|
fromPre = fromNode.getPreUpdateNode() and
|
||||||
toPre = toNode.getPreUpdateNode()
|
toPre = toNode.getPreUpdateNode()
|
||||||
@@ -688,14 +772,20 @@ private module Cached {
|
|||||||
// Does the language-specific simpleLocalFlowStep already model flow
|
// Does the language-specific simpleLocalFlowStep already model flow
|
||||||
// from function input to output?
|
// from function input to output?
|
||||||
fromPre = getAnOutNode(c, _) and
|
fromPre = getAnOutNode(c, _) and
|
||||||
toPre.(ArgumentNode).argumentOf(c, _) and
|
toPre.(ArgNode).argumentOf(c, _) and
|
||||||
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
|
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
|
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
|
* Holds if the call context `call` either improves virtual dispatch in
|
||||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
* `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) {
|
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||||
reducedViableImplInCallContext(_, callable, call)
|
reducedViableImplInCallContext(_, callable, call)
|
||||||
or
|
or
|
||||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
@@ -726,12 +816,12 @@ private module Cached {
|
|||||||
cached
|
cached
|
||||||
newtype TLocalFlowCallContext =
|
newtype TLocalFlowCallContext =
|
||||||
TAnyLocalCall() or
|
TAnyLocalCall() or
|
||||||
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
|
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TReturnKindExt =
|
newtype TReturnKindExt =
|
||||||
TValueReturn(ReturnKind kind) or
|
TValueReturn(ReturnKind kind) or
|
||||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||||
|
|
||||||
cached
|
cached
|
||||||
newtype TBooleanOption =
|
newtype TBooleanOption =
|
||||||
@@ -761,23 +851,15 @@ private module Cached {
|
|||||||
* A `Node` at which a cast can occur such that the type should be checked.
|
* A `Node` at which a cast can occur such that the type should be checked.
|
||||||
*/
|
*/
|
||||||
class CastingNode extends Node {
|
class CastingNode extends Node {
|
||||||
CastingNode() {
|
CastingNode() { castingNode(this) }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate readStepWithTypes(
|
private predicate readStepWithTypes(
|
||||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||||
) {
|
) {
|
||||||
readStep(n1, c, n2) and
|
read(n1, c, n2) and
|
||||||
container = getNodeType(n1) and
|
container = getNodeDataFlowType(n1) and
|
||||||
content = getNodeType(n2)
|
content = getNodeDataFlowType(n2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private newtype TReadStepTypesOption =
|
private newtype TReadStepTypesOption =
|
||||||
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
|||||||
override string toString() { result = "CcSomeCall" }
|
override string toString() { result = "CcSomeCall" }
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
override predicate relevantFor(DataFlowCallable callable) {
|
||||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate matchesCall(DataFlowCall call) { any() }
|
override predicate matchesCall(DataFlowCall call) { any() }
|
||||||
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate relevantFor(DataFlowCallable callable) {
|
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) {
|
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
|
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
|
* 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.
|
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||||
*/
|
*/
|
||||||
class ReturnNodeExt extends Node {
|
class ReturnNodeExt extends Node {
|
||||||
ReturnNodeExt() {
|
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||||
this instanceof ReturnNode or
|
|
||||||
parameterValueFlowsToPreUpdate(_, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the kind of this returned value. */
|
/** Gets the kind of this returned value. */
|
||||||
ReturnKindExt getKind() {
|
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||||
result = TValueReturn(this.(ReturnNode).getKind())
|
|
||||||
or
|
|
||||||
exists(ParameterNode p, int pos |
|
|
||||||
parameterValueFlowsToPreUpdate(p, this) and
|
|
||||||
p.isParameterOf(_, pos) and
|
|
||||||
result = TParamUpdate(pos)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
|
|||||||
* or a post-update node associated with a call argument.
|
* or a post-update node associated with a call argument.
|
||||||
*/
|
*/
|
||||||
class OutNodeExt extends Node {
|
class OutNodeExt extends Node {
|
||||||
OutNodeExt() {
|
OutNodeExt() { outNodeExt(this) }
|
||||||
this instanceof OutNode
|
|
||||||
or
|
|
||||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
|||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
/** Gets a node corresponding to data flow out of `call`. */
|
/** 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 {
|
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||||
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
|||||||
ReturnKind getKind() { result = kind }
|
ReturnKind getKind() { result = kind }
|
||||||
|
|
||||||
override string toString() { result = kind.toString() }
|
override string toString() { result = kind.toString() }
|
||||||
|
|
||||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
|
||||||
result = getAnOutNode(call, this.getKind())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||||
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
|||||||
int getPosition() { result = pos }
|
int getPosition() { result = pos }
|
||||||
|
|
||||||
override string toString() { result = "param update " + 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. */
|
/** A callable tagged with a relevant return kind. */
|
||||||
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
|
|||||||
*/
|
*/
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||||
exists(Node n0 |
|
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
|
||||||
pragma[only_bind_into](n0) = n and
|
}
|
||||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
|
||||||
)
|
/** 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]
|
pragma[noinline]
|
||||||
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
|
|||||||
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
cc instanceof CallContextAny and callable = viableCallableExt(call)
|
||||||
or
|
or
|
||||||
exists(DataFlowCallable c0, DataFlowCall call0 |
|
exists(DataFlowCallable c0, DataFlowCall call0 |
|
||||||
call0.getEnclosingCallable() = callable and
|
callEnclosingCallable(call0, callable) and
|
||||||
cc = TReturn(c0, call0) and
|
cc = TReturn(c0, call0) and
|
||||||
c0 = prunedViableImplInCallContextReverse(call0, call)
|
c0 = prunedViableImplInCallContextReverse(call0, call)
|
||||||
)
|
)
|
||||||
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
|||||||
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
result = viableCallableExt(call) and cc instanceof CallContextReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate read = readStep/3;
|
|
||||||
|
|
||||||
/** An optional Boolean value. */
|
/** An optional Boolean value. */
|
||||||
class BooleanOption extends TBooleanOption {
|
class BooleanOption extends TBooleanOption {
|
||||||
string toString() {
|
string toString() {
|
||||||
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
|||||||
|
|
||||||
TypedContent getHead() { this = TFrontHead(result) }
|
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 {
|
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||||
|
|||||||
@@ -228,7 +228,6 @@ module EssaFlow {
|
|||||||
* data flow. It is a strict subset of the `localFlowStep` predicate, as it
|
* data flow. It is a strict subset of the `localFlowStep` predicate, as it
|
||||||
* excludes SSA flow through instance fields.
|
* excludes SSA flow through instance fields.
|
||||||
*/
|
*/
|
||||||
cached
|
|
||||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
// If there is ESSA-flow out of a node `node`, we want flow
|
// If there is ESSA-flow out of a node `node`, we want flow
|
||||||
// both out of `node` and any post-update node of `node`.
|
// both out of `node` and any post-update node of `node`.
|
||||||
@@ -1559,7 +1558,6 @@ predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node no
|
|||||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||||
* in `x.f = newValue`.
|
* in `x.f = newValue`.
|
||||||
*/
|
*/
|
||||||
cached
|
|
||||||
predicate clearsContent(Node n, Content c) {
|
predicate clearsContent(Node n, Content c) {
|
||||||
exists(CallNode call, CallableValue callable, string name |
|
exists(CallNode call, CallableValue callable, string name |
|
||||||
call_unpacks(call, _, callable, name, _) and
|
call_unpacks(call, _, callable, name, _) and
|
||||||
|
|||||||
@@ -9,36 +9,42 @@ private import semmle.python.dataflow.new.internal.TaintTrackingPublic
|
|||||||
*/
|
*/
|
||||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||||
|
|
||||||
/**
|
private module Cached {
|
||||||
* Holds if the additional step from `nodeFrom` to `nodeTo` should be included in all
|
/**
|
||||||
* global taint flow configurations.
|
* Holds if the additional step from `nodeFrom` to `nodeTo` should be included in all
|
||||||
*/
|
* global taint flow configurations.
|
||||||
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
*/
|
||||||
localAdditionalTaintStep(nodeFrom, nodeTo)
|
cached
|
||||||
or
|
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
|
localAdditionalTaintStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||||
|
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||||
|
* different objects.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
|
concatStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
subscriptStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
stringManipulation(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
containerStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
copyStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
forStep(nodeFrom, nodeTo)
|
||||||
|
or
|
||||||
|
unpackingAssignmentStep(nodeFrom, nodeTo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
import Cached
|
||||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
|
||||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
|
||||||
* different objects.
|
|
||||||
*/
|
|
||||||
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
|
||||||
concatStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
subscriptStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
stringManipulation(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
containerStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
copyStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
forStep(nodeFrom, nodeTo)
|
|
||||||
or
|
|
||||||
unpackingAssignmentStep(nodeFrom, nodeTo)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to concatenation.
|
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to concatenation.
|
||||||
|
|||||||
Reference in New Issue
Block a user