Compare commits

...

52 Commits

Author SHA1 Message Date
Philip Ginsbach
065d8a60af use new meaning of super keyword 2021-05-13 11:36:01 +01:00
Philip Ginsbach
8cdd8b6ae0 use instanceof extensions in javascript 2021-05-12 18:58:45 +01:00
Erik Krogh Kristensen
0194af9432 convert field based range pattern to casting based range pattern 2021-05-12 16:49:43 +02:00
Anders Schack-Mulligen
7974e3ad38 Merge pull request #5883 from zbazztian/consider-boxed-booleans-to-avoid-xxe-fps
Consider boxed booleans to avoid false positives for XXE.ql
2021-05-12 12:51:22 +02:00
Sebastian Bauersfeld
b05512a958 Add change notes. 2021-05-12 16:58:24 +07:00
Sebastian Bauersfeld
bf4d88175c Consider boxed booleans to avoid false positives for XXE.ql 2021-05-12 16:40:00 +07:00
Geoffrey White
8f152b7380 Merge pull request #5877 from MathiasVP/detect-more-abs-in-overflow-library
C++: Detect more uses of `abs`
2021-05-12 10:02:12 +01:00
Tom Hvitved
fc121e1cbd Merge pull request #5865 from tamasvajk/feature/remove-base-class-dependency-id
C#: Remove base class from type IDs in trap files
2021-05-12 10:30:31 +02:00
Anders Schack-Mulligen
a247ae4357 Merge pull request #5843 from JLLeitschuh/feat/JLL/improve_kryo_support
[Java] Fix Kryo FP & Kryo 5 Support
2021-05-12 09:52:24 +02:00
Anders Schack-Mulligen
74ae2e0857 Merge pull request #5773 from hvitved/dataflow/aggressive-caching
Data flow: Cache most language-dependent predicates
2021-05-12 09:41:55 +02:00
Tamas Vajk
8e371fd05a Adjust expected IR test file 2021-05-11 21:54:05 +02:00
Mathias Vorreiter Pedersen
948f1d8e34 C++: Add testcase with INTMAX_MIN. 2021-05-11 19:43:21 +02:00
Geoffrey White
d7e560c611 Merge pull request #5767 from ihsinme/ihsinme-patch-268
CPP: Add query for CWE-1126: Declaration of Variable with Unnecessarily Wide Scope
2021-05-11 15:24:25 +01:00
Mathias Vorreiter Pedersen
3e21f479a9 C++: Add change-note. 2021-05-11 14:58:48 +02:00
Tom Hvitved
d66506b0a3 Data flow: Rename {Argument,Parameter}NodeExt to {Arg,Param}Node 2021-05-11 14:40:10 +02:00
Mathias Vorreiter Pedersen
48e783184c C++: Fix false positive by recognizing more absolute value functions in Overflow.qll 2021-05-11 14:30:28 +02:00
Jonathan Leitschuh
0d9a85ca6b Update java/change-notes/2021-05-05-kryo-improvements.md
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2021-05-11 08:29:50 -04:00
Mathias Vorreiter Pedersen
24d8abd2c2 C++: Add false positive testcase when an absolute value is used in comparison. 2021-05-11 14:27:53 +02:00
Tamas Vajk
717070c7e4 Fix/cleanup passed and default arguments values 2021-05-11 13:11:35 +02:00
Jonathan Leitschuh
d27316eb3e Apply suggestions from code review
Co-authored-by: Marcono1234 <Marcono1234@users.noreply.github.com>
2021-05-10 11:55:31 -04:00
Tamas Vajk
dd86da3f24 C#: Remove base class from type IDs in trap files 2021-05-10 17:06:10 +02:00
Tamas Vajk
31ac6442e8 C#: Fix default parameter value generation in case of error symbols 2021-05-10 17:03:08 +02:00
ihsinme
9e5a38debd Update DeclarationOfVariableWithUnnecessarilyWideScope.expected 2021-05-10 14:17:40 +03:00
ihsinme
d3c6093f37 Update test.c 2021-05-10 14:16:38 +03:00
ihsinme
c8f2937df9 Update DeclarationOfVariableWithUnnecessarilyWideScope.ql 2021-05-10 14:16:11 +03:00
Jonathan Leitschuh
67e9f06304 [Java] Fix Kryo FP & Kryo 5 Support
Closes #4992
2021-05-05 17:38:34 -04:00
ihsinme
976ccda135 Update DeclarationOfVariableWithUnnecessarilyWideScope.ql 2021-05-05 23:34:21 +03:00
ihsinme
b277082462 Update DeclarationOfVariableWithUnnecessarilyWideScope.qhelp 2021-05-05 23:28:04 +03:00
ihsinme
bb97507ebc Update test.c 2021-05-02 22:59:56 +03:00
ihsinme
21f43252e6 Update DeclarationOfVariableWithUnnecessarilyWideScope.expected 2021-05-02 22:59:04 +03:00
ihsinme
0935c5a0f2 Update DeclarationOfVariableWithUnnecessarilyWideScope.ql 2021-05-02 22:58:30 +03:00
ihsinme
8c3980d80b Update cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2021-05-02 22:54:43 +03:00
Tom Hvitved
c35a2b959a Python: Update data-flow caching 2021-04-28 14:49:05 +02:00
Tom Hvitved
e8347c2c20 C++: Update data-flow caching 2021-04-28 14:49:05 +02:00
Tom Hvitved
bd0a196a39 Java: Update data-flow caching 2021-04-27 19:06:39 +02:00
Tom Hvitved
befc80b3cb C#: Update data-flow caching 2021-04-27 19:06:39 +02:00
Tom Hvitved
914184f3dd Data flow: Sync files 2021-04-27 19:06:39 +02:00
Tom Hvitved
0c8886967b Data flow: Cache nodeIsHidden 2021-04-27 19:05:11 +02:00
Tom Hvitved
1112c0f994 Data flow: Cache ParameterNode 2021-04-27 19:05:11 +02:00
Tom Hvitved
7d4feaca2f Data flow: Cache ArgumentNode 2021-04-27 19:05:11 +02:00
Tom Hvitved
ade99c2c2b Data flow: Cache Cast(ing)Node 2021-04-27 19:05:11 +02:00
Tom Hvitved
346af4f97a Data flow: Cache ReturnNodeExt 2021-04-27 19:05:10 +02:00
Tom Hvitved
9738de2cb9 Data flow: Cache OutNodeExt 2021-04-27 19:05:10 +02:00
Tom Hvitved
23113c4ff7 Data flow: Cache isUnreachableInCall 2021-04-27 19:05:10 +02:00
Tom Hvitved
1bf0e01a83 Data flow: Cache clearsContent 2021-04-27 19:05:10 +02:00
Tom Hvitved
4009c01558 Data flow: Cache readStep 2021-04-27 19:05:10 +02:00
Tom Hvitved
96aa182893 Data flow: Cache jumpStep 2021-04-27 19:05:10 +02:00
Tom Hvitved
8bfeae768f Data flow: Cache simpleLocalFlowStep 2021-04-27 19:05:10 +02:00
Tom Hvitved
1a56f0b79c Data flow: Cache getNodeType 2021-04-27 19:05:10 +02:00
Tom Hvitved
044c92016b Data flow: Cache enclosing callable predicates 2021-04-27 19:05:09 +02:00
ihsinme
98f7f70814 Add files via upload 2021-04-25 22:35:40 +03:00
ihsinme
50c63a88c3 Add files via upload 2021-04-25 22:34:41 +03:00
90 changed files with 8048 additions and 3420 deletions

View 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.

View File

@@ -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.

View File

@@ -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>

View File

@@ -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"

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -35,22 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +118,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeType(node))
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
t = getNodeType(node) and
t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
jumpStep(node, mid) and
jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,7 +227,7 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
/**
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
* collapsing the two stages.
*/
cached
predicate forceCachingInSameStage() { any() }
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
cached
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
c = call.getEnclosingCallable()
}
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
cached
predicate outNodeExt(Node n) {
n instanceof OutNode
or
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
predicate hiddenNode(Node n) { nodeIsHidden(n) }
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
}
cached
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
)
}
cached
predicate castNode(Node n) { n instanceof CastNode }
cached
predicate castingNode(Node n) {
castNode(n) or
n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
read(_, _, n)
}
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNode).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
}
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +353,11 @@ private module Cached {
* dispatch into account.
*/
cached
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +408,30 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
readStep(mid, _, node) and
read(mid, _, node) and
read = true
)
or
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
predicate cand(ParameterNode p, Node n) {
predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +499,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +530,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
) {
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +577,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
predicate getterStep(ArgumentNode arg, Content c, Node out) {
predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +634,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
callable = call.getEnclosingCallable() and
callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +692,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +724,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +734,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
cached
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +761,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +772,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +794,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +816,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +851,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
CastingNode() {
this instanceof ParameterNode or
this instanceof CastNode or
this instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
readStep(_, _, this)
}
CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParamNode extends Node {
ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
}
/** A data-flow node that represents a call argument. */
class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
ReturnNodeExt() {
this instanceof ReturnNode or
parameterValueFlowsToPreUpdate(_, this)
}
ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
ReturnKindExt getKind() {
result = TValueReturn(this.(ReturnNode).getKind())
or
exists(ParameterNode p, int pos |
parameterValueFlowsToPreUpdate(p, this) and
p.isParameterOf(_, pos) and
result = TParamUpdate(pos)
)
}
ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
OutNodeExt() {
this instanceof OutNode
or
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
}
OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
abstract OutNodeExt getAnOutNode(DataFlowCall call);
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
override OutNodeExt getAnOutNode(DataFlowCall call) {
result = getAnOutNode(call, this.getKind())
}
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
override OutNodeExt getAnOutNode(DataFlowCall call) {
exists(ArgumentNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, this.getPosition())
)
}
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = n0.getEnclosingCallable()
)
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
/** Gets the type of `n` used for type pruning. */
pragma[inline]
DataFlowType getNodeDataFlowType(Node n) {
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
call0.getEnclosingCallable() = callable and
callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
predicate read = readStep/3;
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -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
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Expr -> Expr
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())

View File

@@ -45,6 +45,7 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
* different objects.
*/
cached
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Taint can flow through expressions that alter the value but preserve
// more than one bit of it _or_ expressions that follow data through

View File

@@ -165,105 +165,132 @@ private predicate nodeIsBarrierEqualityCandidate(
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
private predicate nodeIsBarrier(DataFlow::Node node) {
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
exists(Variable checkedVar, Operand access |
/*
* 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)
cached
private module Cached {
cached
predicate nodeIsBarrier(DataFlow::Node node) {
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
// 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
)
exists(Variable checkedVar, Operand access |
/*
* 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)
)
}
cached
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
// 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) {
// 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()
}
private import Cached
/**
* Holds if `tainted` may contain taint from `source`.
@@ -402,19 +429,7 @@ module TaintedWithPath {
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
)
or
// Step to return value of a modeled function when an input taints the
// 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()
)
additionalTaintStep(n1, n2)
}
override predicate isSanitizer(DataFlow::Node node) {

View File

@@ -2,11 +2,14 @@ private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import DataFlowImplCommon as DataFlowImplCommon
/**
* Gets a function that might be called by `call`.
*/
cached
Function viableCallable(CallInstruction call) {
DataFlowImplCommon::forceCachingInSameStage() and
result = call.getStaticCallTarget()
or
// 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();
/** Gets a candidate target for this call. */
cached
abstract Function resolve();
/**

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -35,22 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +118,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeType(node))
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
t = getNodeType(node) and
t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
jumpStep(node, mid) and
jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,7 +227,7 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
/**
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
* collapsing the two stages.
*/
cached
predicate forceCachingInSameStage() { any() }
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
cached
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
c = call.getEnclosingCallable()
}
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
cached
predicate outNodeExt(Node n) {
n instanceof OutNode
or
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
predicate hiddenNode(Node n) { nodeIsHidden(n) }
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
}
cached
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
)
}
cached
predicate castNode(Node n) { n instanceof CastNode }
cached
predicate castingNode(Node n) {
castNode(n) or
n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
read(_, _, n)
}
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNode).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
}
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +353,11 @@ private module Cached {
* dispatch into account.
*/
cached
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +408,30 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
readStep(mid, _, node) and
read(mid, _, node) and
read = true
)
or
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
predicate cand(ParameterNode p, Node n) {
predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +499,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +530,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
) {
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +577,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
predicate getterStep(ArgumentNode arg, Content c, Node out) {
predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +634,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
callable = call.getEnclosingCallable() and
callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +692,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +724,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +734,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
cached
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +761,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +772,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +794,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +816,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +851,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
CastingNode() {
this instanceof ParameterNode or
this instanceof CastNode or
this instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
readStep(_, _, this)
}
CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParamNode extends Node {
ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
}
/** A data-flow node that represents a call argument. */
class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
ReturnNodeExt() {
this instanceof ReturnNode or
parameterValueFlowsToPreUpdate(_, this)
}
ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
ReturnKindExt getKind() {
result = TValueReturn(this.(ReturnNode).getKind())
or
exists(ParameterNode p, int pos |
parameterValueFlowsToPreUpdate(p, this) and
p.isParameterOf(_, pos) and
result = TParamUpdate(pos)
)
}
ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
OutNodeExt() {
this instanceof OutNode
or
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
}
OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
abstract OutNodeExt getAnOutNode(DataFlowCall call);
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
override OutNodeExt getAnOutNode(DataFlowCall call) {
result = getAnOutNode(call, this.getKind())
}
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
override OutNodeExt getAnOutNode(DataFlowCall call) {
exists(ArgumentNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, this.getPosition())
)
}
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = n0.getEnclosingCallable()
)
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
/** Gets the type of `n` used for type pruning. */
pragma[inline]
DataFlowType getNodeDataFlowType(Node n) {
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
call0.getEnclosingCallable() = callable and
callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
predicate read = readStep/3;
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -12,10 +12,20 @@ private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.models.interfaces.DataFlow
cached
private newtype TIRDataFlowNode =
TInstructionNode(Instruction i) or
TOperandNode(Operand op) or
TVariableNode(Variable var)
private module Cached {
cached
newtype TIRDataFlowNode =
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.
@@ -590,7 +600,7 @@ Node uninitializedNode(LocalVariable v) { none() }
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
predicate localFlowStep = localFlowStepCached/2;
/**
* 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
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Operand -> Instruction flow
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())

View File

@@ -12,7 +12,7 @@ import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
* Holds if the value of `use` is guarded using `abs`.
*/
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
guardedLesser(e, fc)
)

View File

@@ -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 |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql

View File

@@ -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--;
}
}

View File

@@ -18,3 +18,25 @@ void useTaintedInt()
y = getTaintedInt();
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]
}
}

View File

@@ -170,7 +170,8 @@ namespace Semmle.Extraction.CSharp.Entities
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
int childIndex, Extraction.Entities.Location location)
{
if (!parameter.HasExplicitDefaultValue)
if (!parameter.HasExplicitDefaultValue ||
parameter.Type is IErrorTypeSymbol)
{
return null;
}

View File

@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(EscapingTextWriter trapFile)
{
Symbol.BuildTypeId(Context, trapFile, Symbol);
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
trapFile.Write(";functionpointertype");
}

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(EscapingTextWriter trapFile)
{
Symbol.BuildTypeId(Context, trapFile, Symbol);
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
trapFile.Write(";tuple");
}

View File

@@ -81,22 +81,45 @@ namespace Semmle.Extraction.CSharp.Entities
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
trapFile.WriteLine("\")");
var baseTypes = GetBaseTypeDeclarations();
// Visit base types
var baseTypes = new List<Type>();
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
{
var baseKey = Create(Context, @base);
trapFile.extend(this, baseKey.TypeRef);
if (Symbol.TypeKind != TypeKind.Struct)
baseTypes.Add(baseKey);
var bts = GetBaseTypeDeclarations(baseTypes, @base);
Context.PopulateLater(() =>
{
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))
{
foreach (var t in base.Symbol.Interfaces.Select(i => Create(Context, i)))
foreach (var i in base.Symbol.Interfaces)
{
trapFile.implement(this, t.TypeRef);
baseTypes.Add(t);
var bts = GetBaseTypeDeclarations(baseTypes, i);
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);
}
if (IsSourceDeclaration && Symbol.FromSource())
private IEnumerable<BaseTypeSyntax> GetBaseTypeDeclarations()
{
if (!IsSourceDeclaration || !Symbol.FromSource())
{
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));
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();
return Enumerable.Empty<BaseTypeSyntax>();
}
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)

View File

@@ -121,8 +121,6 @@ namespace Semmle.Extraction.CSharp
named = named.TupleUnderlyingType;
if (IdDependsOnImpl(named.ContainingType))
return true;
if (IdDependsOnImpl(named.GetNonObjectBaseType(cx)))
return true;
if (IdDependsOnImpl(named.ConstructedFrom))
return true;
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="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>
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
type.BuildTypeId(cx, trapFile, symbolBeingDefined, true, constructUnderlyingTupleType);
private static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
using (cx.StackGuard)
{
@@ -171,7 +166,7 @@ namespace Semmle.Extraction.CSharp
{
case TypeKind.Array:
var array = (IArrayTypeSymbol)type;
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
array.BuildArraySuffix(trapFile);
return;
case TypeKind.Class:
@@ -181,16 +176,16 @@ namespace Semmle.Extraction.CSharp
case TypeKind.Delegate:
case TypeKind.Error:
var named = (INamedTypeSymbol)type;
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
return;
case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type;
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('*');
return;
case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type;
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('_');
trapFile.Write(tp.Name);
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)
{
@@ -232,7 +227,7 @@ namespace Semmle.Extraction.CSharp
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
trapFile.Write("__self__");
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)
trapFile.WriteSubId(NamedType.CreateNamedTypeFromTupleType(cx, namedType));
else
@@ -250,7 +245,7 @@ namespace Semmle.Extraction.CSharp
/// <paramref name="symbol" />.
/// </summary>
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>
/// 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));
}
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)
{
@@ -297,7 +292,7 @@ namespace Semmle.Extraction.CSharp
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
}
);
trapFile.Write(")");
@@ -308,7 +303,7 @@ namespace Semmle.Extraction.CSharp
{
if (named.ContainingType is not null)
{
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('.');
}
else if (named.ContainingNamespace is not null)
@@ -333,35 +328,17 @@ namespace Semmle.Extraction.CSharp
}
else
{
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
trapFile.Write('<');
// Encode the nullability of the type arguments in the label.
// Type arguments with different nullability can result in
// a constructed type with different nullability of its members and methods,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass)
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false)
);
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)

View File

@@ -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
module UnificationStage {
private import semmle.code.csharp.Unification

View File

@@ -1,10 +1,10 @@
private import csharp
private import cil
private import dotnet
private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPublic
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.Caching
private import semmle.code.csharp.dataflow.FlowSummary
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.frameworks.system.Collections
@@ -68,31 +68,30 @@ private predicate transitiveCapturedCallTarget(ControlFlow::Nodes::ElementNode c
)
}
cached
private module Cached {
cached
newtype TReturnKind =
TNormalReturnKind() { Stages::DataFlowStage::forceCachingInSameStage() } or
TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
TImplicitCapturedReturnKind(LocalScopeVariable v) {
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
v = def.getSourceVariable().getAssignable()
)
} or
TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
rk instanceof NormalReturnKind and
(
target instanceof Constructor or
not target.getReturnType() instanceof VoidType
)
or
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
}
newtype TReturnKind =
TNormalReturnKind() or
TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
TImplicitCapturedReturnKind(LocalScopeVariable v) {
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
v = def.getSourceVariable().getAssignable()
)
} or
TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
rk instanceof NormalReturnKind and
(
target instanceof Constructor or
not target.getReturnType() instanceof VoidType
)
or
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
}
private module Cached {
cached
newtype TDataFlowCall =
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
DataFlowImplCommon::forceCachingInSameStage() and
cfn.getElement() = dc.getCall()
} or
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
@@ -246,7 +245,6 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlow::Node getNode();
/** Gets the enclosing callable of this call. */
cached
abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying expression, if any. */
@@ -280,10 +278,7 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
override DataFlowCallable getEnclosingCallable() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = cfn.getEnclosingCallable()
}
override DataFlowCallable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
override string toString() { result = cfn.toString() }

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -35,22 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +118,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeType(node))
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
t = getNodeType(node) and
t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
jumpStep(node, mid) and
jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,7 +227,7 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
/**
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
* collapsing the two stages.
*/
cached
predicate forceCachingInSameStage() { any() }
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
cached
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
c = call.getEnclosingCallable()
}
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
cached
predicate outNodeExt(Node n) {
n instanceof OutNode
or
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
predicate hiddenNode(Node n) { nodeIsHidden(n) }
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
}
cached
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
)
}
cached
predicate castNode(Node n) { n instanceof CastNode }
cached
predicate castingNode(Node n) {
castNode(n) or
n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
read(_, _, n)
}
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNode).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
}
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +353,11 @@ private module Cached {
* dispatch into account.
*/
cached
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +408,30 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
readStep(mid, _, node) and
read(mid, _, node) and
read = true
)
or
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
predicate cand(ParameterNode p, Node n) {
predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +499,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +530,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
) {
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +577,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
predicate getterStep(ArgumentNode arg, Content c, Node out) {
predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +634,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
callable = call.getEnclosingCallable() and
callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +692,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +724,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +734,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
cached
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +761,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +772,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +794,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +816,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +851,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
CastingNode() {
this instanceof ParameterNode or
this instanceof CastNode or
this instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
readStep(_, _, this)
}
CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParamNode extends Node {
ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
}
/** A data-flow node that represents a call argument. */
class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
ReturnNodeExt() {
this instanceof ReturnNode or
parameterValueFlowsToPreUpdate(_, this)
}
ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
ReturnKindExt getKind() {
result = TValueReturn(this.(ReturnNode).getKind())
or
exists(ParameterNode p, int pos |
parameterValueFlowsToPreUpdate(p, this) and
p.isParameterOf(_, pos) and
result = TParamUpdate(pos)
)
}
ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
OutNodeExt() {
this instanceof OutNode
or
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
}
OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
abstract OutNodeExt getAnOutNode(DataFlowCall call);
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
override OutNodeExt getAnOutNode(DataFlowCall call) {
result = getAnOutNode(call, this.getKind())
}
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
override OutNodeExt getAnOutNode(DataFlowCall call) {
exists(ArgumentNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, this.getPosition())
)
}
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = n0.getEnclosingCallable()
)
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
/** Gets the type of `n` used for type pruning. */
pragma[inline]
DataFlowType getNodeDataFlowType(Node n) {
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
call0.getEnclosingCallable() = callable and
callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
predicate read = readStep/3;
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -7,7 +7,6 @@ private import DataFlowImplCommon
private import ControlFlowReachability
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.FlowSummary
private import semmle.code.csharp.Caching
private import semmle.code.csharp.Conversion
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
private import semmle.code.csharp.ExprOrStmtParent
@@ -21,7 +20,6 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
abstract class NodeImpl extends Node {
/** Do not call: use `getEnclosingCallable()` instead. */
cached
abstract DataFlowCallable getEnclosingCallableImpl();
/** Do not call: use `getType()` instead. */
@@ -29,9 +27,8 @@ abstract class NodeImpl extends Node {
abstract DotNet::Type getTypeImpl();
/** Gets the type of this node used for type pruning. */
cached
Gvn::GvnType getDataFlowType() {
Stages::DataFlowStage::forceCachingInSameStage() and
forceCachingInSameStage() and
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
t0 = getCSharpType(this.getType())
or
@@ -55,26 +52,25 @@ abstract class NodeImpl extends Node {
private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getExpr().getEnclosingCallable()
}
override DotNet::Type getTypeImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
forceCachingInSameStage() and
result = this.getExpr().getType()
}
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and this = TExprNode(result)
forceCachingInSameStage() and this = TExprNode(result)
}
override Location getLocationImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and result = this.getExpr().getLocation()
forceCachingInSameStage() and result = this.getExpr().getLocation()
}
override string toStringImpl() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getControlFlowNode().toString()
forceCachingInSameStage() and
result = this.getControlFlowNodeImpl().toString()
or
exists(CIL::Expr e |
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]
private Expr getImplicitArgument(Call c, int pos) {
result = c.getArgument(pos) and
@@ -582,12 +594,16 @@ private Type getCSharpType(DotNet::Type 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`. */
private class DataFlowTypeOrUnifiable extends Gvn::GvnType {
pragma[nomagic]
DataFlowTypeOrUnifiable() {
this instanceof DataFlowType or
Gvn::unifiable(any(DataFlowType t), this)
this instanceof RelevantDataFlowType or
Gvn::unifiable(any(RelevantDataFlowType t), this)
}
}
@@ -598,7 +614,7 @@ private TypeParameter getATypeParameterSubType(DataFlowTypeOrUnifiable t) {
}
pragma[noinline]
private TypeParameter getATypeParameterSubTypeRestricted(DataFlowType t) {
private TypeParameter getATypeParameterSubTypeRestricted(RelevantDataFlowType t) {
result = getATypeParameterSubType(t)
}
@@ -614,17 +630,30 @@ private Gvn::GvnType getANonTypeParameterSubType(DataFlowTypeOrUnifiable t) {
}
pragma[noinline]
private Gvn::GvnType getANonTypeParameterSubTypeRestricted(DataFlowType t) {
private Gvn::GvnType getANonTypeParameterSubTypeRestricted(RelevantDataFlowType t) {
result = getANonTypeParameterSubType(t)
}
/** A collection of cached types and predicates to be evaluated in the same stage. */
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
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
Stages::DataFlowStage::forceCachingInSameStage() and cfn.getElement() instanceof Expr
forceCaching() and
cfn.getElement() instanceof Expr
} or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TSsaDefinitionNode(Ssa::Definition def) {
@@ -679,23 +708,6 @@ private module Cached {
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
* (intra-procedural) step.
@@ -714,178 +726,14 @@ private module Cached {
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
newtype TContent =
TFieldContent(Field f) { f.isUnboundDeclaration() } or
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
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]
private PropertyContent getResultContent() {
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) {
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, RelevantDataFlowType t2) {
not t1 instanceof Gvn::TypeParameterGvnType and
t1 = t2
or
@@ -899,102 +747,53 @@ private module Cached {
* `t2` are allowed to be type parameters.
*/
cached
predicate commonSubType(DataFlowType t1, DataFlowType t2) { commonSubTypeGeneral(t1, t2) }
predicate commonSubType(RelevantDataFlowType t1, RelevantDataFlowType t2) {
commonSubTypeGeneral(t1, t2)
}
cached
predicate commonSubTypeUnifiableLeft(DataFlowType t1, DataFlowType t2) {
predicate commonSubTypeUnifiableLeft(RelevantDataFlowType t1, RelevantDataFlowType t2) {
exists(Gvn::GvnType t |
Gvn::unifiable(t1, t) and
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
/** 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. */
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
Ssa::Definition def;
@@ -1142,10 +941,12 @@ import ParameterNodes
/** A data-flow node that represents a call argument. */
class ArgumentNode extends Node {
ArgumentNode() { argumentNode(this, _, _) }
ArgumentNode() { this instanceof ArgumentNodeImpl }
/** 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 {
@@ -1310,14 +1111,10 @@ private module ArgumentNodes {
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
private DataFlowCall c;
private int i;
SummaryArgumentNode() { summaryArgumentNodeCached(c, this, i) }
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
override predicate argumentOf(DataFlowCall call, int pos) {
call = c and
i = pos
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
}
}
}
@@ -1352,7 +1149,16 @@ private module ReturnNodes {
class OutRefReturnNode extends ReturnNode, SsaDefinitionNode {
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 }
}
@@ -1449,7 +1255,10 @@ private module ReturnNodes {
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() { summaryReturnNodeCached(this, rk) }
SummaryReturnNode() {
FlowSummaryImpl::Private::summaryReturnNode(this, rk) and
not rk instanceof JumpReturnKind
}
override ReturnKind getKind() { result = rk }
}
@@ -1460,7 +1269,6 @@ import ReturnNodes
/** A data-flow node that represents the output of a call. */
abstract class OutNode extends Node {
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
cached
abstract DataFlowCall getCall(ReturnKind kind);
}
@@ -1488,7 +1296,6 @@ private module OutNodes {
}
override DataFlowCall getCall(ReturnKind kind) {
Stages::DataFlowStage::forceCachingInSameStage() and
result = call and
(
kind instanceof NormalReturnKind and
@@ -1564,14 +1371,10 @@ private module OutNodes {
}
private class SummaryOutNode extends SummaryNode, OutNode {
private DataFlowCall c;
private ReturnKind rk;
SummaryOutNode() { summaryOutNodeCached(c, this, rk) }
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
override DataFlowCall getCall(ReturnKind kind) {
result = c and
kind = rk
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
}
}
}
@@ -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 {
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 {
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
@@ -1753,10 +1709,7 @@ predicate readStep = readStepImpl/3;
* `DataFlowType`, while `Func<T, int>` and `Func<string, int>` are not, because
* `string` is not a type parameter.
*/
class DataFlowType extends Gvn::GvnType {
pragma[nomagic]
DataFlowType() { this = any(NodeImpl n).getDataFlowType() }
}
class DataFlowType = Gvn::GvnType;
/** Gets the type of `n` used for type pruning. */
pragma[inline]
@@ -1888,11 +1841,11 @@ private module PostUpdateNodes {
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) }
SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
override Node getPreUpdateNode() { result = pre }
override Node getPreUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
}
}
}
@@ -1900,7 +1853,12 @@ private import PostUpdateNodes
/** A node that performs a type cast. */
class CastNode extends Node {
CastNode() { castNode(this) }
CastNode() {
this.asExpr() instanceof Cast
or
this.(AssignableDefinitionNode).getDefinition() instanceof
AssignableDefinitions::PatternDefinition
}
}
class DataFlowExpr = DotNet::Expr;

View File

@@ -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.
*
@@ -74,9 +76,7 @@ class Node extends TNode {
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
class ExprNode extends Node {
ExprNode() { this = TExprNode(_) or this = TCilExprNode(_) }
class ExprNode extends Node, TExprNode_ {
/** Gets the expression corresponding to this node. */
DotNet::Expr getExpr() {
result = this.getExprAtNode(_)
@@ -99,7 +99,7 @@ class ExprNode extends Node {
* flow graph.
*/
class ParameterNode extends Node {
ParameterNode() { parameterNode(this, _, _) }
ParameterNode() { this instanceof ParameterNodeImpl }
/** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter getParameter() {
@@ -110,7 +110,9 @@ class ParameterNode extends Node {
* 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) }
predicate isParameterOf(DataFlowCallable c, int i) {
this.(ParameterNodeImpl).isParameterOf(c, i)
}
}
/** A definition, viewed as a node in a data flow graph. */

View File

@@ -1,6 +1,5 @@
private import csharp
private import TaintTrackingPublic
private import DataFlowImplCommon
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.Caching
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) {
Stages::DataFlowStage::forceCachingInSameStage() and
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
or
localTaintStepCil(nodeFrom, nodeTo)
@@ -87,6 +85,11 @@ private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node n
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
* (intra-procedural) step.

View File

@@ -529,7 +529,7 @@ function_pointer_return_type(
int return_type_id: @type_or_ref ref);
extend(
unique int sub: @type ref,
int sub: @type ref,
int super: @type_or_ref ref);
anonymous_types(

View File

@@ -613,13 +613,13 @@ foreach.cs:
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
# 5| r5_29(Int32) = Constant[7] :
# 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_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
# 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
# 7| Block 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Removed unique base class constraint
compatibility: backwards

View 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)

View 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.

View File

@@ -292,6 +292,7 @@ private predicate summaryModelCsv(string row) {
"java.util;StringTokenizer;false;StringTokenizer;;;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.kryo5.io;Input;false;Input;;;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;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint",

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -35,22 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +118,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeType(node))
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
t = getNodeType(node) and
t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
jumpStep(node, mid) and
jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,7 +227,7 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
/**
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
* collapsing the two stages.
*/
cached
predicate forceCachingInSameStage() { any() }
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
cached
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
c = call.getEnclosingCallable()
}
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
cached
predicate outNodeExt(Node n) {
n instanceof OutNode
or
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
predicate hiddenNode(Node n) { nodeIsHidden(n) }
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
}
cached
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
)
}
cached
predicate castNode(Node n) { n instanceof CastNode }
cached
predicate castingNode(Node n) {
castNode(n) or
n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
read(_, _, n)
}
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNode).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
}
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +353,11 @@ private module Cached {
* dispatch into account.
*/
cached
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +408,30 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
readStep(mid, _, node) and
read(mid, _, node) and
read = true
)
or
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
predicate cand(ParameterNode p, Node n) {
predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +499,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +530,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
) {
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +577,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
predicate getterStep(ArgumentNode arg, Content c, Node out) {
predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +634,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
callable = call.getEnclosingCallable() and
callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +692,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +724,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +734,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
cached
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +761,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +772,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +794,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +816,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +851,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
CastingNode() {
this instanceof ParameterNode or
this instanceof CastNode or
this instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
readStep(_, _, this)
}
CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParamNode extends Node {
ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
}
/** A data-flow node that represents a call argument. */
class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
ReturnNodeExt() {
this instanceof ReturnNode or
parameterValueFlowsToPreUpdate(_, this)
}
ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
ReturnKindExt getKind() {
result = TValueReturn(this.(ReturnNode).getKind())
or
exists(ParameterNode p, int pos |
parameterValueFlowsToPreUpdate(p, this) and
p.isParameterOf(_, pos) and
result = TParamUpdate(pos)
)
}
ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
OutNodeExt() {
this instanceof OutNode
or
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
}
OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
abstract OutNodeExt getAnOutNode(DataFlowCall call);
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
override OutNodeExt getAnOutNode(DataFlowCall call) {
result = getAnOutNode(call, this.getKind())
}
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
override OutNodeExt getAnOutNode(DataFlowCall call) {
exists(ArgumentNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, this.getPosition())
)
}
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = n0.getEnclosingCallable()
)
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
/** Gets the type of `n` used for type pruning. */
pragma[inline]
DataFlowType getNodeDataFlowType(Node n) {
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
call0.getEnclosingCallable() = callable and
callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
predicate read = readStep/3;
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -4,71 +4,48 @@ private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.TypeFlow
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
private import DataFlowImplCommon as DataFlowImplCommon
cached
private module Cached {
cached
newtype TNode =
TExprNode(Expr e) {
not e.getType() instanceof VoidType and
not e.getParent*() instanceof Annotation
} or
TExplicitParameterNode(Parameter p) {
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
} or
TImplicitVarargsArray(Call c) {
c.getCallee().isVarargs() and
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
} or
TInstanceParameterNode(Callable c) {
(exists(c.getBody()) or c instanceof SummarizedCallable) and
not c.isStatic()
} or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
TMallocNode(ClassInstanceExpr cie) or
TExplicitExprPostUpdate(Expr e) {
explicitInstanceArgument(_, e)
or
e instanceof Argument and not e.getType() instanceof ImmutableType
or
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
or
exists(ArrayAccess aa | e = aa.getArray())
} or
TImplicitExprPostUpdate(InstanceAccessExt ia) {
implicitInstanceArgument(_, ia)
or
exists(FieldAccess fa |
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
}
cached
predicate summaryOutNodeCached(DataFlowCall c, Node out) {
FlowSummaryImpl::Private::summaryOutNode(c, out, _)
newtype TNode =
TExprNode(Expr e) {
DataFlowImplCommon::forceCachingInSameStage() and
not e.getType() instanceof VoidType and
not e.getParent*() instanceof Annotation
} or
TExplicitParameterNode(Parameter p) {
exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
} or
TImplicitVarargsArray(Call c) {
c.getCallee().isVarargs() and
not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
} or
TInstanceParameterNode(Callable c) {
(exists(c.getBody()) or c instanceof SummarizedCallable) and
not c.isStatic()
} or
TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
TMallocNode(ClassInstanceExpr cie) or
TExplicitExprPostUpdate(Expr e) {
explicitInstanceArgument(_, e)
or
e instanceof Argument and not e.getType() instanceof ImmutableType
or
exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
or
exists(ArrayAccess aa | e = aa.getArray())
} or
TImplicitExprPostUpdate(InstanceAccessExt ia) {
implicitInstanceArgument(_, ia)
or
exists(FieldAccess fa |
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
}
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) {
call instanceof MethodAccess and
instarg = call.getQualifier() and
@@ -404,13 +381,15 @@ module Private {
override string toString() { result = "[summary] " + state + " in " + c }
/** 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. */
predicate isReturn() { summaryReturnNodeCached(this) }
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this, _) }
/** 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) {
@@ -439,7 +418,7 @@ private class MallocNode extends Node, TMallocNode {
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
override Node getPreUpdateNode() { result = pre }
}

View File

@@ -284,7 +284,6 @@ private class ConstantBooleanArgumentNode extends ArgumentNode, ExprNode {
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/
cached
predicate isUnreachableInCall(Node n, DataFlowCall call) {
exists(
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param,

View File

@@ -11,6 +11,7 @@ private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.FlowSummary
import semmle.code.java.dataflow.InstanceAccess
private import FlowSummaryImpl as FlowSummaryImpl
private import TaintTrackingUtil as TaintTrackingUtil
import DataFlowNodes::Public
/** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */
@@ -112,6 +113,7 @@ predicate localFlowStep(Node node1, Node node2) {
*/
cached
predicate simpleLocalFlowStep(Node node1, Node node2) {
TaintTrackingUtil::forceCachingInSameStage() and
// Variable flow steps through adjacent def-use and use-use pairs.
exists(SsaExplicitUpdate upd |
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or

View File

@@ -29,55 +29,69 @@ predicate localExprTaint(Expr src, Expr sink) {
localTaint(DataFlow::exprNode(src), DataFlow::exprNode(sink))
}
/**
* Holds if taint can flow in one local step from `src` to `sink`.
*/
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)
cached
private module Cached {
private import DataFlowImplCommon as DataFlowImplCommon
cached
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
/**
* 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
}
}
/**
* 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
}
import Cached
/**
* Holds if taint can flow in one local step from `src` to `sink` excluding

View File

@@ -3,19 +3,60 @@
*/
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSteps
/**
* The type `com.esotericsoftware.kryo.Kryo`.
*/
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.
*/
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")
}
}

View File

@@ -48,6 +48,65 @@ class SafeKryo extends DataFlow2::Configuration {
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) {

View File

@@ -36,7 +36,10 @@ abstract class ParserConfig extends MethodAccess {
*/
predicate disables(Expr e) {
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) {
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")
)
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,7 @@
package com.esotericsoftware.kryo.pool;
import com.esotericsoftware.kryo.Kryo;
public interface KryoCallback<T> {
T execute (Kryo kryo);
}

View File

@@ -0,0 +1,7 @@
package com.esotericsoftware.kryo.pool;
import com.esotericsoftware.kryo.Kryo;
public interface KryoFactory {
Kryo create ();
}

View File

@@ -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;
}
}
}

View File

@@ -6,16 +6,13 @@ import javascript
module Base64 {
/** A call to a base64 encoder. */
class Encode extends DataFlow::Node {
Encode::Range encode;
Encode() { this = encode }
class Encode extends DataFlow::Node instanceof Encode::Range {
/** 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. */
DataFlow::Node getOutput() { result = encode.getOutput() }
DataFlow::Node getOutput() { result = super.getOutput() }
}
module Encode {
@@ -34,16 +31,13 @@ module Base64 {
}
/** A call to a base64 decoder. */
class Decode extends DataFlow::Node {
Decode::Range encode;
Decode() { this = encode }
class Decode extends DataFlow::Node instanceof Decode::Range {
/** 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. */
DataFlow::Node getOutput() { result = encode.getOutput() }
DataFlow::Node getOutput() { result = super.getOutput() }
}
module Decode {

View File

@@ -8,15 +8,14 @@ module Closure {
/**
* A reference to a Closure namespace.
*/
class ClosureNamespaceRef extends DataFlow::Node {
ClosureNamespaceRef::Range range;
ClosureNamespaceRef() { this = range }
class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range {
/**
* Gets the namespace being referenced.
*/
string getClosureNamespace() { result = range.getClosureNamespace() }
string getClosureNamespace() {
result = super.getClosureNamespace()
}
}
module ClosureNamespaceRef {
@@ -36,8 +35,7 @@ module Closure {
/**
* A data flow node that returns the value of a closure namespace.
*/
class ClosureNamespaceAccess extends ClosureNamespaceRef {
override ClosureNamespaceAccess::Range range;
class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range {
}
module ClosureNamespaceAccess {
@@ -80,8 +78,7 @@ module Closure {
/**
* A top-level call to `goog.provide`.
*/
class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode {
override DefaultClosureProvideCall range;
class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall {
}
/**
@@ -94,8 +91,7 @@ module Closure {
/**
* A call to `goog.require`.
*/
class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode {
override DefaultClosureRequireCall range;
class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall {
}
/**
@@ -111,8 +107,7 @@ module Closure {
/**
* A top-level call to `goog.module` or `goog.declareModuleId`.
*/
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode {
override DefaultClosureModuleDeclaration range;
class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration {
}
private GlobalVariable googVariable() { variables(result, "goog", any(GlobalScope sc)) }

View File

@@ -16,16 +16,13 @@ private import javascript
* ~A.indexOf(B)
* ```
*/
class InclusionTest extends DataFlow::Node {
InclusionTest::Range range;
InclusionTest() { this = range }
class InclusionTest extends DataFlow::Node instanceof InclusionTest::Range {
/** 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)`. */
DataFlow::Node getContainedNode() { result = range.getContainedNode() }
DataFlow::Node getContainedNode() { result = super.getContainedNode() }
/**
* 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
* the given element.
*/
boolean getPolarity() { result = range.getPolarity() }
boolean getPolarity() { result = super.getPolarity() }
}
module InclusionTest {

View File

@@ -9,27 +9,24 @@ import javascript
*
* Additional candidates can be added by subclassing `MembershipCandidate::Range`
*/
class MembershipCandidate extends DataFlow::Node {
MembershipCandidate::Range range;
MembershipCandidate() { this = range }
class MembershipCandidate extends DataFlow::Node instanceof MembershipCandidate::Range {
/**
* 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
* it can be determined.
*/
string getAMemberString() { result = range.getAMemberString() }
string getAMemberString() { result = super.getAMemberString() }
/**
* Gets a node that this candidate is tested against, if
* it can be determined.
*/
DataFlow::Node getAMemberNode() { result = range.getAMemberNode() }
DataFlow::Node getAMemberNode() { result = super.getAMemberNode() }
/**
* 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
* collection does not contain this candidate.
*/
boolean getTestPolarity() { result = range.getTestPolarity() }
boolean getTestPolarity() { result = super.getTestPolarity() }
}
/**

View File

@@ -8,20 +8,17 @@ module StringOps {
/**
* A expression that is equivalent to `A.startsWith(B)` or `!A.startsWith(B)`.
*/
class StartsWith extends DataFlow::Node {
StartsWith::Range range;
StartsWith() { range = this }
class StartsWith extends DataFlow::Node instanceof StartsWith::Range {
/**
* 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)`.
*/
DataFlow::Node getSubstring() { result = range.getSubstring() }
DataFlow::Node getSubstring() { result = super.getSubstring() }
/**
* 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
* with the given substring.
*/
boolean getPolarity() { result = range.getPolarity() }
boolean getPolarity() { result = super.getPolarity() }
}
module StartsWith {
@@ -237,20 +234,17 @@ module StringOps {
/**
* An expression that is equivalent to `A.endsWith(B)` or `!A.endsWith(B)`.
*/
class EndsWith extends DataFlow::Node {
EndsWith::Range range;
EndsWith() { this = range }
class EndsWith extends DataFlow::Node instanceof EndsWith::Range {
/**
* 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)`.
*/
DataFlow::Node getSubstring() { result = range.getSubstring() }
DataFlow::Node getSubstring() { result = super.getSubstring() }
/**
* 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
* with the given substring.
*/
boolean getPolarity() { result = range.getPolarity() }
boolean getPolarity() { result = super.getPolarity() }
}
module EndsWith {
@@ -662,10 +656,7 @@ module StringOps {
* if (!match) { ... } // <--- 'match' is the RegExpTest
* ```
*/
class RegExpTest extends DataFlow::Node {
RegExpTest::Range range;
RegExpTest() { this = range }
class RegExpTest extends DataFlow::Node instanceof RegExpTest::Range {
/**
* 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() {
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
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.
*/
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.
*/
DataFlow::Node getStringOperand() { result = range.getStringOperand() }
DataFlow::Node getStringOperand() { result = super.getStringOperand() }
/**
* 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
* `regexp.exec(str) != null` the polarity is `true`.
*/
boolean getPolarity() { result = range.getPolarity() }
boolean getPolarity() { result = super.getPolarity() }
}
/**

View File

@@ -701,13 +701,10 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode {
* define(["fs"], function(fs) { ... }); // AMD module
* ```
*/
class ModuleImportNode extends DataFlow::SourceNode {
ModuleImportNode::Range range;
ModuleImportNode() { this = range }
class ModuleImportNode extends DataFlow::SourceNode instanceof ModuleImportNode::Range {
/** Gets the path of the imported module. */
string getPath() { result = range.getPath() }
string getPath() { result = super.getPath() }
}
module ModuleImportNode {
@@ -843,25 +840,22 @@ module MemberKind {
*
* Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`.
*/
class ClassNode extends DataFlow::SourceNode {
ClassNode::Range impl;
ClassNode() { this = impl }
class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
/**
* 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.
*/
string describe() { result = impl.describe() }
string describe() { result = super.describe() }
/**
* 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.
@@ -869,7 +863,7 @@ class ClassNode extends DataFlow::SourceNode {
* Does not include methods from superclasses.
*/
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.
*/
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.
@@ -887,7 +883,7 @@ class ClassNode extends DataFlow::SourceNode {
* Does not include members from superclasses.
*/
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.
*/
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.
*
* 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.
*/
FunctionNode getStaticMethod(string name) { result = impl.getStaticMethod(name) }
FunctionNode getStaticMethod(string name) {
result = super.getStaticMethod(name)
}
/**
* Gets a static method declared in this class.
*
* 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.
*/
DataFlow::Node getASuperClassNode() { result = impl.getASuperClassNode() }
DataFlow::Node getASuperClassNode() { result = super.getASuperClassNode() }
/**
* 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.
*/
TypeAnnotation getFieldTypeAnnotation(string fieldName) {
result = impl.getFieldTypeAnnotation(fieldName)
result = super.getFieldTypeAnnotation(fieldName)
}
/**
* Gets a decorator applied to this class.
*/
DataFlow::Node getADecorator() { result = impl.getADecorator() }
DataFlow::Node getADecorator() { result = super.getADecorator() }
}
module ClassNode {
@@ -1357,10 +1357,7 @@ module ClassNode {
* _.partial(fn, x, y, z)
* ```
*/
class PartialInvokeNode extends DataFlow::Node {
PartialInvokeNode::Range range;
PartialInvokeNode() { this = range }
class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range {
/** Gets a node holding a callback invoked by this partial invocation node. */
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`.
*/
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.
*/
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.
*/
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.
*/
DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
result = range.getBoundReceiver(callback)
result = super.getBoundReceiver(callback)
}
}

View File

@@ -32,10 +32,7 @@ module Cheerio {
* Creation of `cheerio` object, a collection of virtual DOM elements
* with an interface similar to that of a jQuery object.
*/
class CheerioObjectCreation extends DataFlow::SourceNode {
CheerioObjectCreation::Range range;
CheerioObjectCreation() { this = range }
class CheerioObjectCreation extends DataFlow::SourceNode instanceof CheerioObjectCreation::Range {
}
module CheerioObjectCreation {

View File

@@ -18,25 +18,22 @@ import javascript
* To model additional APIs, extend `ClientRequest::Range` and implement its abstract member
* predicates.
*/
class ClientRequest extends DataFlow::InvokeNode {
ClientRequest::Range self;
ClientRequest() { this = self }
class ClientRequest extends DataFlow::InvokeNode instanceof ClientRequest::Range {
/**
* Gets the URL of the request.
*/
DataFlow::Node getUrl() { result = self.getUrl() }
DataFlow::Node getUrl() { result = super.getUrl() }
/**
* 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.
*/
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
@@ -60,7 +57,7 @@ class ClientRequest extends DataFlow::InvokeNode {
* - Any value provided by custom implementations of `ClientRequest::Range`.
*/
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.
*/
DataFlow::Node getASavePath() { result = self.getASavePath() }
DataFlow::Node getASavePath() { result = super.getASavePath() }
}
deprecated class CustomClientRequest = ClientRequest::Range;

View File

@@ -8,10 +8,7 @@ import javascript
* A call to a function that constructs a function composition `f(g(h(...)))` from a
* series functions `f, g, h, ...`.
*/
class FunctionCompositionCall extends DataFlow::CallNode {
FunctionCompositionCall::Range range;
FunctionCompositionCall() { this = range }
class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionCompositionCall::Range {
/**
* 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,
* 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. */
final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) }
@@ -38,7 +37,7 @@ class FunctionCompositionCall extends DataFlow::CallNode {
final DataFlow::Node getAnOperandFunction() { result = getOperandFunction(_) }
/** Gets the number of functions being composed. */
int getNumOperand() { result = range.getNumOperand() }
int getNumOperand() { result = super.getNumOperand() }
}
/**

View File

@@ -181,8 +181,7 @@ module Electron {
/**
* A Node.js-style HTTP or HTTPS request made using an Electron module.
*/
class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest {
override ElectronClientRequest::Range self;
class ElectronClientRequest extends NodeJSLib::NodeJSClientRequest instanceof ElectronClientRequest::Range {
}
module ElectronClientRequest {

View File

@@ -68,40 +68,40 @@ module EventEmitter {
* An EventEmitter instance that implements the EventEmitter API.
* Extend EventEmitter::Range to mark something as being an EventEmitter.
*/
class EventEmitter extends DataFlow::Node {
EventEmitter::Range range;
EventEmitter() { this = range }
class EventEmitter extends DataFlow::Node instanceof EventEmitter::Range {
}
/**
* A registration of an event handler on an EventEmitter.
*/
class EventRegistration extends DataFlow::Node {
EventRegistration::Range range;
EventRegistration() { this = range }
class EventRegistration extends DataFlow::Node instanceof EventRegistration::Range {
/** 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. */
string getChannel() { result = range.getChannel() }
string getChannel() { result = super.getChannel() }
/** 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.
* 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.
* The default implementation is that there exists no such dispatch.
*/
EventDispatch getAReturnDispatch() { result = range.getAReturnDispatch() }
EventDispatch getAReturnDispatch() {
result = super.getAReturnDispatch()
}
}
module EventRegistration {
@@ -140,26 +140,23 @@ module EventRegistration {
/**
* A dispatch of an event on an EventEmitter.
*/
class EventDispatch extends DataFlow::Node {
EventDispatch::Range range;
EventDispatch() { this = range }
class EventDispatch extends DataFlow::Node instanceof EventDispatch::Range {
/** 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. */
string getChannel() { result = range.getChannel() }
string getChannel() { result = this.(EventDispatch::Range).getChannel() }
/** 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.
* The default implementation is that the emitters of the dispatch and registration have to be equal.
* Channels are by default ignored.
*/
EventRegistration getAReceiver() { result = range.getAReceiver() }
EventRegistration getAReceiver() { result = super.getAReceiver() }
}
module EventDispatch {

View File

@@ -540,16 +540,13 @@ module HTTP {
/**
* An object that contains one or more potential route handlers.
*/
class RouteHandlerCandidateContainer extends DataFlow::Node {
RouteHandlerCandidateContainer::Range self;
RouteHandlerCandidateContainer() { this = self }
class RouteHandlerCandidateContainer extends DataFlow::Node instanceof RouteHandlerCandidateContainer::Range {
/**
* Gets the route handler in this container that is accessed at `access`.
*/
DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
result = self.getRouteHandler(access)
result = super.getRouteHandler(access)
}
}

View File

@@ -831,8 +831,7 @@ module NodeJSLib {
* A data flow node that is an HTTP or HTTPS client request made by a Node.js application,
* for example `http.request(url)`.
*/
class NodeJSClientRequest extends ClientRequest {
override NodeJSClientRequest::Range self;
class NodeJSClientRequest extends ClientRequest instanceof NodeJSClientRequest::Range {
}
module NodeJSClientRequest {

View File

@@ -14,20 +14,17 @@ import javascript
* To model additional APIs, extend `PropertyProjection::Range` and implement its abstract member
* predicates.
*/
class PropertyProjection extends DataFlow::CallNode {
PropertyProjection::Range self;
PropertyProjection() { this = self }
class PropertyProjection extends DataFlow::CallNode instanceof PropertyProjection::Range {
/**
* 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')`.
*/
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.
@@ -36,7 +33,7 @@ class PropertyProjection extends DataFlow::CallNode {
* - 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'}`,
*/
predicate isSingletonProjection() { self.isSingletonProjection() }
predicate isSingletonProjection() { super.isSingletonProjection() }
}
module PropertyProjection {

View File

@@ -56,10 +56,7 @@ module Redux {
/**
* Creation of a redux store, usually via a call to `createStore`.
*/
class StoreCreation extends DataFlow::SourceNode {
StoreCreation::Range range;
StoreCreation() { this = range }
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
/** Gets a reference to the store. */
DataFlow::SourceNode ref() { result = asApiNode().getAUse() }
@@ -68,7 +65,7 @@ module Redux {
API::Node asApiNode() { result.getAnImmediateUse() = this }
/** 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. */
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
* at some point. We model all action creators as if they dispatch the action they create.
*/
class ActionCreator extends DataFlow::SourceNode {
ActionCreator::Range range;
ActionCreator() { this = range }
class ActionCreator extends DataFlow::SourceNode instanceof ActionCreator::Range {
/** 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
@@ -442,7 +436,7 @@ module Redux {
* the action payload. Otherwise, the return value is the payload itself.
*/
DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
result = range.getMiddlewareFunction(async)
result = super.getMiddlewareFunction(async)
}
/** Gets a data flow node referring to this action creator. */

View File

@@ -14,13 +14,10 @@ module ShellJS {
}
/** A member of the `shelljs` library. */
class Member extends DataFlow::SourceNode {
Member::Range range;
Member() { this = range }
class Member extends DataFlow::SourceNode instanceof Member::Range {
/** 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 {

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
jumpStep(node1, node2) and
jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
exists(ArgumentNode arg |
exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -944,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1260,8 +1252,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
castNode(this) or
clearsContentCached(this, _)
}
}
@@ -1275,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1313,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1342,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = getNodeType(node2) and
t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1376,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1435,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2081,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2300,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
TSummaryCtxSome(ParameterNode p, AccessPath ap) {
TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParameterNode p;
private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2749,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2970,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
nodeIsHidden(this.getNode()) and
hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3139,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(getNodeType(node))
ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
exists(ParameterNode p |
exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParameterNode p)
TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3582,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3602,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3616,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3774,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3788,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3804,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3818,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
exists(ArgumentNode arg |
exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
exists(ParameterNode p |
exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
exists(PartialPathNodeRev mid, ParameterNode p |
exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and

View File

@@ -35,22 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +118,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeType(node))
if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
t = getNodeType(node) and
t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
jumpStep(node, mid) and
jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
t = getNodeType(node)
t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,7 +227,7 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
@@ -242,6 +242,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
/**
* If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
* force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
* collapsing the two stages.
*/
cached
predicate forceCachingInSameStage() { any() }
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
cached
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
c = call.getEnclosingCallable()
}
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
cached
predicate outNodeExt(Node n) {
n instanceof OutNode
or
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
predicate hiddenNode(Node n) { nodeIsHidden(n) }
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
}
cached
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
)
}
cached
predicate castNode(Node n) { n instanceof CastNode }
cached
predicate castingNode(Node n) {
castNode(n) or
n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
read(_, _, n)
}
cached
predicate parameterNode(Node n, DataFlowCallable c, int i) {
n.(ParameterNode).isParameterOf(c, i)
}
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
}
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +353,11 @@ private module Cached {
* dispatch into account.
*/
cached
predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +408,30 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
readStep(mid, _, node) and
read(mid, _, node) and
read = true
)
or
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
predicate cand(ParameterNode p, Node n) {
predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +499,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +530,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(
ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
) {
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +577,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
predicate getterStep(ArgumentNode arg, Content c, Node out) {
predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParameterNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +634,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
callable = call.getEnclosingCallable() and
callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +692,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +724,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +734,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
cached
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +761,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +772,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +794,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +816,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +851,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
CastingNode() {
this instanceof ParameterNode or
this instanceof CastNode or
this instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
readStep(_, _, this)
}
CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +948,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +981,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +995,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParamNode extends Node {
ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
}
/** A data-flow node that represents a call argument. */
class ArgNode extends Node {
ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
}
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
ReturnNodeExt() {
this instanceof ReturnNode or
parameterValueFlowsToPreUpdate(_, this)
}
ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
ReturnKindExt getKind() {
result = TValueReturn(this.(ReturnNode).getKind())
or
exists(ParameterNode p, int pos |
parameterValueFlowsToPreUpdate(p, this) and
p.isParameterOf(_, pos) and
result = TParamUpdate(pos)
)
}
ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1033,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
OutNodeExt() {
this instanceof OutNode
or
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
}
OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1046,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
abstract OutNodeExt getAnOutNode(DataFlowCall call);
final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1057,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
override OutNodeExt getAnOutNode(DataFlowCall call) {
result = getAnOutNode(call, this.getKind())
}
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1067,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
override OutNodeExt getAnOutNode(DataFlowCall call) {
exists(ArgumentNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, this.getPosition())
)
}
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1093,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
pragma[only_bind_into](result) = n0.getEnclosingCallable()
)
nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
/** Gets the type of `n` used for type pruning. */
pragma[inline]
DataFlowType getNodeDataFlowType(Node n) {
nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1123,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
call0.getEnclosingCallable() = callable and
callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1144,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
predicate read = readStep/3;
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1195,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -228,7 +228,6 @@ module EssaFlow {
* data flow. It is a strict subset of the `localFlowStep` predicate, as it
* excludes SSA flow through instance fields.
*/
cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// If there is ESSA-flow out of a node `node`, we want flow
// 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`
* in `x.f = newValue`.
*/
cached
predicate clearsContent(Node n, Content c) {
exists(CallNode call, CallableValue callable, string name |
call_unpacks(call, _, callable, name, _) and

View File

@@ -9,36 +9,42 @@ private import semmle.python.dataflow.new.internal.TaintTrackingPublic
*/
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* 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)
or
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
private module Cached {
/**
* Holds if the additional step from `nodeFrom` to `nodeTo` should be included in all
* global taint flow configurations.
*/
cached
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node 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)
}
}
/**
* 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)
}
import Cached
/**
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to concatenation.