mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge branch 'main' into rdmarsh/cpp/use-taint-configuration-dtt
This commit is contained in:
2
.github/workflows/docs-review.yml
vendored
2
.github/workflows/docs-review.yml
vendored
@@ -26,4 +26,4 @@ jobs:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
gh pr comment "$PR_NUMBER" --repo "github/codeql" \
|
||||
--body "Hello @github/docs-content-codeql: this PR is ready for docs review."
|
||||
--body "Hello @github/docs-content-codeql - this PR is ready for docs review."
|
||||
|
||||
60
.github/workflows/generate-query-help-docs.yml
vendored
60
.github/workflows/generate-query-help-docs.yml
vendored
@@ -1,60 +0,0 @@
|
||||
name: Generate CodeQL query help documentation using Sphinx
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
description:
|
||||
description: A description of the purpose of this job. For human consumption.
|
||||
required: false
|
||||
push:
|
||||
branches:
|
||||
- 'lgtm.com'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/generate-query-help-docs.yml'
|
||||
- 'docs/codeql/query-help/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone github/codeql
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: codeql
|
||||
- name: Clone github/codeql-go
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'github/codeql-go'
|
||||
path: codeql-go
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Download CodeQL CLI
|
||||
uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c
|
||||
with:
|
||||
repo: "github/codeql-cli-binaries"
|
||||
version: "latest"
|
||||
file: "codeql-linux64.zip"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Unzip CodeQL CLI
|
||||
run: unzip -d codeql-cli codeql-linux64.zip
|
||||
- name: Set up query help docs folder
|
||||
run: |
|
||||
cp -r codeql/docs/codeql/** .
|
||||
- name: Query help to markdown
|
||||
run: |
|
||||
PATH="$PATH:codeql-cli/codeql" python codeql/docs/codeql/query-help-markdown.py
|
||||
- name: Run Sphinx for query help
|
||||
uses: ammaraskar/sphinx-action@8b4f60114d7fd1faeba1a712269168508d4750d2 # v0.4
|
||||
with:
|
||||
docs-folder: "query-help/"
|
||||
pre-build-command: "python -m pip install --upgrade recommonmark && python -m pip install --upgrade sphinx-markdown-tables"
|
||||
build-command: "sphinx-build -b dirhtml . _build"
|
||||
- name: Upload HTML artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: query-help-html
|
||||
path: query-help/_build
|
||||
|
||||
@@ -38,23 +38,38 @@ predicate isNonEscapingArgument(Expr escaped) {
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionCall call, LocalVariable v, MemsetFunction memset
|
||||
where
|
||||
call.getTarget() = memset and
|
||||
not isFromMacroDefinition(call) and
|
||||
// `v` escapes as the argument to `memset`
|
||||
variableAddressEscapesTree(v.getAnAccess(), call.getArgument(0).getFullyConverted()) and
|
||||
// ... and `v` doesn't escape anywhere else.
|
||||
forall(Expr escape | variableAddressEscapesTree(v.getAnAccess(), escape) |
|
||||
isNonEscapingArgument(escape)
|
||||
) and
|
||||
pragma[noinline]
|
||||
predicate callToMemsetWithRelevantVariable(
|
||||
LocalVariable v, VariableAccess acc, FunctionCall call, MemsetFunction memset
|
||||
) {
|
||||
not v.isStatic() and
|
||||
// Reference-typed variables get special treatment in `variableAddressEscapesTree` so we leave them
|
||||
// out of this query.
|
||||
not v.getUnspecifiedType() instanceof ReferenceType and
|
||||
// `v` is not only just used in the call to `memset`.
|
||||
exists(Access acc |
|
||||
acc = v.getAnAccess() and not call.getArgument(0).getAChild*() = acc and not acc.isUnevaluated()
|
||||
call.getTarget() = memset and
|
||||
acc = v.getAnAccess() and
|
||||
// `v` escapes as the argument to `memset`
|
||||
variableAddressEscapesTree(acc, call.getArgument(0).getFullyConverted())
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate relevantVariable(LocalVariable v, FunctionCall call, MemsetFunction memset) {
|
||||
exists(VariableAccess acc, VariableAccess anotherAcc |
|
||||
callToMemsetWithRelevantVariable(v, acc, call, memset) and
|
||||
// `v` is not only just used in the call to `memset`.
|
||||
anotherAcc = v.getAnAccess() and
|
||||
acc != anotherAcc and
|
||||
not anotherAcc.isUnevaluated()
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionCall call, LocalVariable v, MemsetFunction memset
|
||||
where
|
||||
relevantVariable(v, call, memset) and
|
||||
not isFromMacroDefinition(call) and
|
||||
// `v` doesn't escape anywhere else.
|
||||
forall(Expr escape | variableAddressEscapesTree(v.getAnAccess(), escape) |
|
||||
isNonEscapingArgument(escape)
|
||||
) and
|
||||
// There is no later use of `v`.
|
||||
not v.getAnAccess() = call.getASuccessor*() and
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
if(len<0) return 1;
|
||||
memset(dest, source, len); // GOOD: variable `len` checked before call
|
||||
|
||||
...
|
||||
|
||||
memset(dest, source, len); // BAD: variable `len` checked after call
|
||||
if(len<0) return 1;
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Checking the function argument after calling the function itself. This situation looks suspicious and requires the attention of the developer. It may be necessary to add validation before calling the function</p>
|
||||
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>We recommend checking before calling the function.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates an erroneous and fixed use of function argument validation.</p>
|
||||
<sample src="LateCheckOfFunctionArgument.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CWE Common Weakness Enumeration:
|
||||
<a href="https://cwe.mitre.org/data/definitions/20.html"> CWE-20: Improper Input Validation</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @name Late Check Of Function Argument
|
||||
* @description --Checking the function argument after calling the function itself.
|
||||
* --This situation looks suspicious and requires the attention of the developer.
|
||||
* --It may be necessary to add validation before calling the function.
|
||||
* @kind problem
|
||||
* @id cpp/late-check-of-function-argument
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/** Holds for a function `f` that has an argument at index `apos` used for positioning in a buffer. */
|
||||
predicate numberArgument(Function f, int apos) {
|
||||
f.hasGlobalOrStdName("write") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("read") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("lseek") and apos = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("memmove") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("memset") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("memcpy") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("memcmp") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("strncat") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("strncpy") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("strncmp") and apos = 2
|
||||
or
|
||||
f.hasGlobalOrStdName("snprintf") and apos = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("strndup") and apos = 2
|
||||
}
|
||||
|
||||
class IfCompareWithZero extends IfStmt {
|
||||
IfCompareWithZero() { this.getCondition().(RelationalOperation).getAChild().getValue() = "0" }
|
||||
|
||||
Expr noZerroOperand() {
|
||||
if this.getCondition().(RelationalOperation).getGreaterOperand().getValue() = "0"
|
||||
then result = this.getCondition().(RelationalOperation).getLesserOperand()
|
||||
else result = this.getCondition().(RelationalOperation).getGreaterOperand()
|
||||
}
|
||||
}
|
||||
|
||||
from FunctionCall fc, IfCompareWithZero ifc, int na
|
||||
where
|
||||
numberArgument(fc.getTarget(), na) and
|
||||
globalValueNumber(fc.getArgument(na)) = globalValueNumber(ifc.noZerroOperand()) and
|
||||
dominates(fc, ifc) and
|
||||
not exists(IfStmt ifc1 |
|
||||
dominates(ifc1, fc) and
|
||||
globalValueNumber(fc.getArgument(na)) = globalValueNumber(ifc1.getCondition().getAChild*())
|
||||
)
|
||||
select fc,
|
||||
"The value of argument '$@' appears to be checked after the call, rather than before it.",
|
||||
fc.getArgument(na), fc.getArgument(na).toString()
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -447,7 +447,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | n.getEnclosingCallable() = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -592,7 +592,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | p.getEnclosingCallable() = callable)
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -637,7 +637,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | n.getEnclosingCallable() = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +746,22 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
string toString() { result = "[" + kind + "] " + c }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
||||
* predicate ensures that joins go from `n` to the result instead of the other
|
||||
* way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) {
|
||||
result = ret.getEnclosingCallable()
|
||||
result = getNodeEnclosingCallable(ret)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -447,7 +447,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | n.getEnclosingCallable() = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -592,7 +592,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | p.getEnclosingCallable() = callable)
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -637,7 +637,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | n.getEnclosingCallable() = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +746,22 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
string toString() { result = "[" + kind + "] " + c }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
||||
* predicate ensures that joins go from `n` to the result instead of the other
|
||||
* way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) {
|
||||
result = ret.getEnclosingCallable()
|
||||
result = getNodeEnclosingCallable(ret)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| test.c:6:3:6:8 | call to memset | The value of argument '$@' appears to be checked after the call, rather than before it. | test.c:6:17:6:20 | len1 | len1 |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql
|
||||
@@ -0,0 +1,8 @@
|
||||
void workFunction_0(char *s) {
|
||||
int len = 5, len1;
|
||||
char buf[80], buf1[8];
|
||||
if(len<0) return;
|
||||
memset(buf,0,len); //GOOD
|
||||
memset(buf1,0,len1); //BAD
|
||||
if(len1<0) return;
|
||||
}
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -447,7 +447,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | n.getEnclosingCallable() = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -592,7 +592,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | p.getEnclosingCallable() = callable)
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -637,7 +637,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | n.getEnclosingCallable() = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +746,22 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
string toString() { result = "[" + kind + "] " + c }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
||||
* predicate ensures that joins go from `n` to the result instead of the other
|
||||
* way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) {
|
||||
result = ret.getEnclosingCallable()
|
||||
result = getNodeEnclosingCallable(ret)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
import re
|
||||
import subprocess
|
||||
import json
|
||||
import csv
|
||||
import sys
|
||||
import os
|
||||
|
||||
"""
|
||||
This script collects CodeQL queries that are part of code scanning query packs,
|
||||
renders the accompanying query help as markdown, inserts some useful metadata
|
||||
into the help, and adds a link to the query in the CodeQL repo.
|
||||
|
||||
This script requires that 'git' and 'codeql' commands
|
||||
are on the PATH. It'll try to automatically set the CodeQL search path correctly,
|
||||
as long as you run the script from one of the following locations:
|
||||
- anywhere from within a clone of the CodeQL Git repo
|
||||
- from the parent directory of a clone of the CodeQL Git repo (assuming 'codeql'
|
||||
and 'codeql-go' directories both exist)
|
||||
"""
|
||||
|
||||
# Define which languages and query packs to consider
|
||||
languages = [ "cpp", "csharp", "go", "java", "javascript", "python"]
|
||||
|
||||
# Query suites to generate help for - lgtm suite should cover the queries that users are interested in
|
||||
packs = ["lgtm"]
|
||||
|
||||
def prefix_repo_nwo(filename):
|
||||
"""
|
||||
Replaces an absolute path prefix with a GitHub repository name with owner (NWO).
|
||||
This function relies on `git` being available.
|
||||
For example:
|
||||
/home/alice/git/ql/java/ql/src/MyQuery.ql
|
||||
becomes:
|
||||
github/codeql/java/ql/src/MyQuery.ql
|
||||
|
||||
If we can't detect a known NWO (e.g. github/codeql, github/codeql-go), the
|
||||
path will be truncated to the root of the git repo:
|
||||
ql/java/ql/src/MyQuery.ql
|
||||
|
||||
If the filename is not part of a Git repo, the return value is the
|
||||
same as the input value: the whole path.
|
||||
"""
|
||||
dirname = os.path.dirname(filename)
|
||||
|
||||
try:
|
||||
git_toplevel_dir_subp = subprocess_run(
|
||||
["git", "-C", dirname, "rev-parse", "--show-toplevel"])
|
||||
except:
|
||||
# Not a Git repo
|
||||
return filename
|
||||
|
||||
git_toplevel_dir = git_toplevel_dir_subp.stdout.strip()
|
||||
|
||||
# Detect 'github/codeql' and 'github/codeql-go' repositories by checking the remote (it's a bit
|
||||
# of a hack but will work in most cases, as long as the remotes have 'codeql' and 'codeql-go'
|
||||
# in the URL
|
||||
git_remotes = subprocess_run(
|
||||
["git", "-C", dirname, "remote", "-v"]).stdout.strip()
|
||||
|
||||
if "codeql-go" in git_remotes:
|
||||
prefix = "github/codeql-go"
|
||||
elif "codeql" in git_remotes:
|
||||
prefix = "github/codeql"
|
||||
else:
|
||||
prefix = os.path.basename(git_toplevel_dir)
|
||||
|
||||
return os.path.join(prefix, filename[len(git_toplevel_dir)+1:])
|
||||
|
||||
|
||||
def single_spaces(input):
|
||||
"""
|
||||
Workaround for https://github.com/github/codeql-coreql-team/issues/470 which causes
|
||||
some metadata strings to contain newlines and spaces without a good reason.
|
||||
"""
|
||||
return " ".join(input.split())
|
||||
|
||||
|
||||
def get_query_metadata(key, metadata, queryfile):
|
||||
"""Returns query metadata or prints a warning to stderr if a particular piece of metadata is not available."""
|
||||
if key in metadata:
|
||||
return single_spaces(metadata[key])
|
||||
query_id = metadata['id'] if 'id' in metadata else 'unknown'
|
||||
print("Warning: no '%s' metadata for query with ID '%s' (%s)" %
|
||||
(key, query_id, queryfile), file=sys.stderr)
|
||||
return ""
|
||||
|
||||
|
||||
def subprocess_run(cmd):
|
||||
"""Runs a command through subprocess.run, with a few tweaks. Raises an Exception if exit code != 0."""
|
||||
return subprocess.run(cmd, capture_output=True, text=True, env=os.environ.copy(), check=True)
|
||||
|
||||
|
||||
try: # Check for `git` on path
|
||||
subprocess_run(["git", "--version"])
|
||||
except Exception as e:
|
||||
print("Error: couldn't invoke 'git'. Is it on the path? Aborting.", file=sys.stderr)
|
||||
raise e
|
||||
|
||||
try: # Check for `codeql` on path
|
||||
subprocess_run(["codeql", "--version"])
|
||||
except Exception as e:
|
||||
print("Error: couldn't invoke CodeQL CLI 'codeql'. Is it on the path? Aborting.", file=sys.stderr)
|
||||
raise e
|
||||
|
||||
# Define CodeQL search path so it'll find the CodeQL repositories:
|
||||
# - anywhere in the current Git clone (including current working directory)
|
||||
# - the 'codeql' subdirectory of the cwd
|
||||
#
|
||||
# (and assumes the codeql-go repo is in a similar location)
|
||||
|
||||
codeql_search_path = "./codeql:./codeql-go" # will be extended further down
|
||||
# Extend CodeQL search path by detecting root of the current Git repo (if any). This means that you
|
||||
# can run this script from any location within the CodeQL git repository.
|
||||
try:
|
||||
git_toplevel_dir = subprocess_run(["git", "rev-parse", "--show-toplevel"])
|
||||
|
||||
# Current working directory is in a Git repo. Add it to the search path, just in case it's the CodeQL repo
|
||||
#git_toplevel_dir = git_toplevel_dir.stdout.strip()
|
||||
codeql_search_path += ":" + git_toplevel_dir + ":" + git_toplevel_dir + "/../codeql-go"
|
||||
codeql_search_path = git_toplevel_dir = git_toplevel_dir.stdout.strip()
|
||||
except:
|
||||
# git rev-parse --show-toplevel exited with non-zero exit code. We're not in a Git repo
|
||||
pass
|
||||
|
||||
# Iterate over all languages and packs, and resolve which queries are part of those packs
|
||||
for lang in languages:
|
||||
|
||||
code_scanning_queries = subprocess_run(
|
||||
["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-code-scanning.qls" % (lang)]).stdout.strip()
|
||||
security_extended_queries = subprocess_run(
|
||||
["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-security-extended.qls" % (lang)]).stdout.strip()
|
||||
security_and_quality_queries = subprocess_run(
|
||||
["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-security-and-quality.qls" % (lang)]).stdout.strip()
|
||||
# Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree
|
||||
index_file_dictionary = {}
|
||||
for pack in packs:
|
||||
# Get absolute paths to queries in this pack by using 'codeql resolve queries'
|
||||
try:
|
||||
|
||||
queries_subp = subprocess_run(
|
||||
["codeql", "resolve", "queries", "--search-path", codeql_search_path, "%s-%s.qls" % (lang, pack)])
|
||||
except Exception as e:
|
||||
# Resolving queries might go wrong if the github/codeql and github/codeql-go repositories are not
|
||||
# on the search path.
|
||||
print(
|
||||
"Warning: couldn't find query pack '%s' for language '%s'. Do you have the right repositories in the right places (search path: '%s')?" % (
|
||||
pack, lang, codeql_search_path),
|
||||
file=sys.stderr
|
||||
)
|
||||
continue
|
||||
|
||||
# Define empty dictionary to store @name:filename pairs to generate alphabetically sorted Sphinx toctree later
|
||||
index_file_dictionary = {}
|
||||
|
||||
# Investigate metadata for every query by using 'codeql resolve metadata'
|
||||
for queryfile in queries_subp.stdout.strip().split("\n"):
|
||||
query_metadata_json = subprocess_run(
|
||||
["codeql", "resolve", "metadata", queryfile]).stdout.strip()
|
||||
meta = json.loads(query_metadata_json)
|
||||
|
||||
# Turn an absolute path to a query file into an nwo-prefixed path (e.g. github/codeql/java/ql/src/....)
|
||||
queryfile_nwo = prefix_repo_nwo(queryfile)
|
||||
|
||||
# Generate the query help for each query
|
||||
try:
|
||||
query_help = subprocess_run(
|
||||
["codeql", "generate", "query-help", "--format=markdown", "--warnings=error", queryfile]).stdout.strip()
|
||||
except:
|
||||
# Print a message if generate query help fails
|
||||
print("Failed to generate query help for '%s'" % (queryfile_nwo))
|
||||
continue
|
||||
|
||||
# Pull out relevant query metadata properties that we want to display in the query help
|
||||
query_name_meta = get_query_metadata('name', meta, queryfile)
|
||||
query_description = get_query_metadata(
|
||||
'description', meta, queryfile)
|
||||
query_id = "ID: " + \
|
||||
get_query_metadata('id', meta, queryfile) + "\n"
|
||||
query_kind = "Kind: " + \
|
||||
get_query_metadata('kind', meta, queryfile) + "\n"
|
||||
query_severity = "Severity: " + \
|
||||
get_query_metadata('problem.severity', meta, queryfile) + "\n"
|
||||
query_precision = "Precision: " + \
|
||||
get_query_metadata('precision', meta, queryfile) + "\n"
|
||||
query_tags = "Tags:\n - " + \
|
||||
get_query_metadata('tags', meta, queryfile).replace(" ", "\n - ") + "\n"
|
||||
|
||||
# Build a link to the query source file for display in the query help
|
||||
if "go" in prefix_repo_nwo(queryfile):
|
||||
transform_link = prefix_repo_nwo(queryfile).replace(
|
||||
"codeql-go", "codeql-go/blob/main").replace(" ", "%20").replace("\\", "/")
|
||||
else:
|
||||
transform_link = prefix_repo_nwo(queryfile).replace(
|
||||
"codeql", "codeql/blob/main").replace(" ", "%20").replace("\\", "/")
|
||||
query_link = "[Click to see the query in the CodeQL repository](https://github.com/" + \
|
||||
transform_link + ")\n"
|
||||
|
||||
if queryfile in code_scanning_queries:
|
||||
cs_suites = ' - ' + lang +'-code-scanning.qls\n'
|
||||
else:
|
||||
cs_suites = ""
|
||||
if queryfile in security_extended_queries:
|
||||
se_suites = ' - ' + lang + '-security-extended.qls\n'
|
||||
else:
|
||||
se_suites = ""
|
||||
if queryfile in security_and_quality_queries:
|
||||
sq_suites = ' - ' +lang + '-security-and-quality.qls\n'
|
||||
else:
|
||||
sq_Suites = ""
|
||||
|
||||
if queryfile in code_scanning_queries or queryfile in security_extended_queries or queryfile in security_and_quality_queries:
|
||||
suites_list = "Query suites:\n" + cs_suites + se_suites + sq_suites
|
||||
else:
|
||||
suites_list = ""
|
||||
|
||||
# Join metadata into a literal block and add query link below
|
||||
meta_string = "\n"*2 + "```\n" + query_id + query_kind + query_severity + \
|
||||
query_precision + query_tags + suites_list + "```\n\n" + query_link + "\n"
|
||||
|
||||
# Insert metadata block into query help directly under title
|
||||
full_help = query_help.replace("\n", meta_string, 1)
|
||||
|
||||
# Use id property to make name for markdown file, replacing any "/" characters with "-"
|
||||
query_name = query_id[4:-1].replace("/", "-")
|
||||
|
||||
# Populate index_file_dictionary with @name extracted from metadata and corresponding query filename
|
||||
index_file_dictionary[query_name_meta] = lang + "/" + query_name
|
||||
|
||||
# Make paths for output of the form: query-help-markdown/<lang>/<queryfile>.md
|
||||
docs_dir = 'query-help'
|
||||
md_dir_path = os.path.join(docs_dir, lang)
|
||||
md_file_path = os.path.join(md_dir_path, query_name + ".md")
|
||||
|
||||
# Make directories for output paths they don't already exist
|
||||
if not os.path.isdir(md_dir_path):
|
||||
os.makedirs(md_dir_path)
|
||||
|
||||
# Generate query help at chosen path if output file doesn't already exist
|
||||
if not os.path.exists(md_file_path):
|
||||
file = open(md_file_path, "x")
|
||||
file.write(full_help)
|
||||
file.close()
|
||||
|
||||
# Sort index_file_dictionary alphabetically by @name key, and create column of filename values
|
||||
sorted_index = dict(sorted(index_file_dictionary.items()))
|
||||
sorted_index = ("\n" + " ").join(sorted_index.values())
|
||||
|
||||
# Add directives to make sorted_index a valid toctree for sphinx source files
|
||||
toc_directive = ".. toctree::\n :titlesonly:\n\n "
|
||||
toc_include = toc_directive + sorted_index
|
||||
|
||||
# Write toctree to rst
|
||||
toc_file = os.path.join(docs_dir, "toc-" + lang + ".rst")
|
||||
file = open(toc_file, "x")
|
||||
file.write(toc_include)
|
||||
file.close()
|
||||
2
java/change-notes/2021-03-02-guava-io.md
Normal file
2
java/change-notes/2021-03-02-guava-io.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Increased coverage of the Guava framework by including classes in the `com.google.common.io` package.
|
||||
2
java/change-notes/2021-03-05-regex-utils.md
Normal file
2
java/change-notes/2021-03-05-regex-utils.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Added models for Apache Commons Lang's `RegExUtils` class. This means that any query that tracks tainted data may return additional results in cases where a `RegExUtils` transformation is part of the path from source to sink.
|
||||
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Increase coverage of the Guava framework, including flow steps through various collection utilities in `com.google.common.collect`, as well as through `Preconditions.checkNotNull`.
|
||||
@@ -8,6 +8,7 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class URLConstructor extends ClassInstanceExpr {
|
||||
@@ -37,6 +38,8 @@ class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration {
|
||||
exists(MethodAccess m |
|
||||
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod
|
||||
)
|
||||
or
|
||||
sinkNode(sink, "url-open-stream")
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
|
||||
@@ -71,6 +71,7 @@ private import internal.DataFlowPrivate
|
||||
private module Frameworks {
|
||||
private import semmle.code.java.frameworks.ApacheHttp
|
||||
private import semmle.code.java.frameworks.apache.Lang
|
||||
private import semmle.code.java.frameworks.guava.Guava
|
||||
}
|
||||
|
||||
private predicate sourceModelCsv(string row) {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -447,7 +447,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | n.getEnclosingCallable() = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -592,7 +592,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | p.getEnclosingCallable() = callable)
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -637,7 +637,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | n.getEnclosingCallable() = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +746,22 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
string toString() { result = "[" + kind + "] " + c }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
||||
* predicate ensures that joins go from `n` to the result instead of the other
|
||||
* way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) {
|
||||
result = ret.getEnclosingCallable()
|
||||
result = getNodeEnclosingCallable(ret)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -376,3 +376,23 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint-propagating models for `RegexUtils`.
|
||||
*/
|
||||
private class ApacheRegExUtilsModel extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
|
||||
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,4 @@ import java
|
||||
import StringUtils
|
||||
import Collections
|
||||
import Preconditions
|
||||
import IO
|
||||
|
||||
98
java/ql/src/semmle/code/java/frameworks/guava/IO.qll
Normal file
98
java/ql/src/semmle/code/java/frameworks/guava/IO.qll
Normal file
@@ -0,0 +1,98 @@
|
||||
/** Definitions of taint steps in the IO package of the Guava framework */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
private class GuavaIoCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;inputspec;outputspec;kind",
|
||||
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;withSeparator;(String,int);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;decode;(CharSequence);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;decodingStream;(Reader);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;decodingSource;(CharSource);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;encode;(byte[]);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;upperCase;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;lowerCase;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;withPadChar;(char);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;omitPadding;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;BaseEncoding;true;encode;(byte[],int,int);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;asCharSource;(Charset);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;concat;;;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;copyTo;(OutputStream);;Argument[-1];Argument[0];taint",
|
||||
"com.google.common.io;ByteSource;true;openStream;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;read;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;ByteStreams;false;copy;(ReadablyByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;newDataInput;(ByteArrayInputStream);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;newDataOutput;(ByteArrayOutputStream);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;ByteStreams;false;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;ByteStreams;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;ByteStreams;false;toByteArray;(InputStream);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;asByteSource;(Charset);;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;concat;;;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;copyTo;(Appendable);;Argument[-1];Argument[0];taint",
|
||||
"com.google.common.io;CharSource;true;openStream;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;openBufferedStream;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;read;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;readFirstLine;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;readLines;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;lines;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;CharSource;true;wrap;(CharSequence);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;CharStreams;false;copy;(Readable,Appendable);;Argument[0];Argument[1];taint",
|
||||
"com.google.common.io;CharStreams;false;readLines;(Readable);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;CharStreams;false;toString;(Readable);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;Closer;true;register;;;Argument[0];ReturnValue;value",
|
||||
"com.google.common.io;Files;false;getFileExtension;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;Files;false;getNameWithoutExtension;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;Files;false;simplifyPath;(String);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;MoreFiles;false;getFileExtension;(Path);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;MoreFiles;false;getNameWithoutExtension;(Path);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;LineReader;false;LineReader;(Readable);;Argument[0];ReturnValue;taint",
|
||||
"com.google.common.io;LineReader;true;readLine;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;toByteArray;();;Argument[-1];ReturnValue;taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[]);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;write;(int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeByte;(int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeBytes;(String);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeChar;(int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeChars;(String);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeDouble;(double);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeFloat;(float);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeInt;(int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeLong;(long);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeShort;(int);;Argument[0];Argument[-1];taint",
|
||||
"com.google.common.io;ByteArrayDataOutput;true;writeUTF;(String);;Argument[0];Argument[-1];taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class GuavaIoSinkCsv extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
//"package;type;overrides;name;signature;ext;inputspec;kind",
|
||||
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;asCharSource;(URL,Charset);;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;copy;(URL,OutputStream);;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;asByteSource;(URL);;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;readLines;;;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;toByteArray;(URL);;Argument[0];url-open-stream",
|
||||
"com.google.common.io;Resources;false;toString;(URL,Charset);;Argument[0];url-open-stream"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class RegExUtilsTest {
|
||||
String taint() { return "tainted"; }
|
||||
|
||||
void sink(Object o) {}
|
||||
|
||||
void test() throws Exception {
|
||||
Pattern cleanPattern = Pattern.compile("clean");
|
||||
Pattern taintedPattern = Pattern.compile(taint());
|
||||
|
||||
sink(RegExUtils.removeAll(taint(), cleanPattern)); // $hasTaintFlow
|
||||
sink(RegExUtils.removeAll(taint(), "clean")); // $hasTaintFlow
|
||||
sink(RegExUtils.removeFirst(taint(), cleanPattern)); // $hasTaintFlow
|
||||
sink(RegExUtils.removeFirst(taint(), "clean")); // $hasTaintFlow
|
||||
sink(RegExUtils.removePattern(taint(), "clean")); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceAll(taint(), cleanPattern, "replacement")); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceAll(taint(), "clean", "replacement")); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceFirst(taint(), cleanPattern, "replacement")); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceFirst(taint(), "clean", "replacement")); // $hasTaintFlow
|
||||
sink(RegExUtils.replacePattern(taint(), "clean", "replacement")); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceAll("original", cleanPattern, taint())); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceAll("original", "clean", taint())); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceFirst("original", cleanPattern, taint())); // $hasTaintFlow
|
||||
sink(RegExUtils.replaceFirst("original", "clean", taint())); // $hasTaintFlow
|
||||
sink(RegExUtils.replacePattern("original", "clean", taint())); // $hasTaintFlow
|
||||
// Subsequent calls don't propagate taint, as regex search patterns don't propagate to the return value.
|
||||
sink(RegExUtils.removeAll("original", taintedPattern));
|
||||
sink(RegExUtils.removeAll("original", taint()));
|
||||
sink(RegExUtils.removeFirst("original", taintedPattern));
|
||||
sink(RegExUtils.removeFirst("original", taint()));
|
||||
sink(RegExUtils.removePattern("original", taint()));
|
||||
sink(RegExUtils.replaceAll("original", taintedPattern, "replacement"));
|
||||
sink(RegExUtils.replaceAll("original", taint(), "replacement"));
|
||||
sink(RegExUtils.replaceFirst("original", taintedPattern, "replacement"));
|
||||
sink(RegExUtils.replaceFirst("original", taint(), "replacement"));
|
||||
sink(RegExUtils.replacePattern("original", taint(), "replacement"));
|
||||
sink(RegExUtils.replaceAll("original", taintedPattern, "replacement"));
|
||||
sink(RegExUtils.replaceAll("original", taint(), "replacement"));
|
||||
sink(RegExUtils.replaceFirst("original", taintedPattern, "replacement"));
|
||||
sink(RegExUtils.replaceFirst("original", taint(), "replacement"));
|
||||
sink(RegExUtils.replacePattern("original", taint(), "replacement"));
|
||||
}
|
||||
}
|
||||
@@ -14,20 +14,20 @@ class TestCollect {
|
||||
String x = taint();
|
||||
|
||||
ImmutableSet<String> xs = ImmutableSet.of(x, "y", "z");
|
||||
sink(xs.asList());
|
||||
sink(xs.asList()); // $numTaintFlow=1
|
||||
|
||||
ImmutableSet<String> ys = ImmutableSet.of("a", "b", "c");
|
||||
|
||||
sink(Sets.filter(Sets.union(xs, ys), y -> true));
|
||||
sink(Sets.filter(Sets.union(xs, ys), y -> true)); // $numTaintFlow=1
|
||||
|
||||
sink(Sets.newHashSet("a", "b", "c", "d", x));
|
||||
sink(Sets.newHashSet("a", "b", "c", "d", x)); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test2() {
|
||||
sink(ImmutableList.of(taint(), taint(), taint(), taint())); // expect 4 alerts
|
||||
sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
|
||||
sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
|
||||
sink(ImmutableTable.of(taint(),taint(), taint())); // expect 1 alert
|
||||
sink(ImmutableList.of(taint(), taint(), taint(), taint())); // $numTaintFlow=4
|
||||
sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2
|
||||
sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // $numTaintFlow=2
|
||||
sink(ImmutableTable.of(taint(),taint(), taint())); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test3() {
|
||||
@@ -38,20 +38,20 @@ class TestCollect {
|
||||
b.add("a");
|
||||
sink(b);
|
||||
b.add(x);
|
||||
sink(b.build());
|
||||
sink(b.build()); // $numTaintFlow=1
|
||||
|
||||
b = ImmutableList.builder();
|
||||
|
||||
b.add("a").add(x);
|
||||
sink(b.build());
|
||||
sink(b.build()); // $numTaintFlow=1
|
||||
|
||||
sink(ImmutableList.builder().add("a").add(x).build());
|
||||
sink(ImmutableList.builder().add("a").add(x).build()); // $numTaintFlow=1
|
||||
|
||||
ImmutableMap.Builder<String, String> b2 = ImmutableMap.builder();
|
||||
b2.put(x,"v");
|
||||
sink(b2);
|
||||
b2.put("k",x);
|
||||
sink(b2.build());
|
||||
sink(b2.build()); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test4(Table<String, String, String> t1, Table<String, String, String> t2, Table<String, String, String> t3) {
|
||||
@@ -61,62 +61,62 @@ class TestCollect {
|
||||
t1.put("r", x, "v");
|
||||
sink(t1);
|
||||
t1.put("r", "c", x);
|
||||
sink(t1);
|
||||
sink(t1.row("r"));
|
||||
sink(t1); // $numTaintFlow=1
|
||||
sink(t1.row("r")); // $numTaintFlow=1
|
||||
|
||||
t2.putAll(t1);
|
||||
for (Table.Cell<String,String,String> c : t2.cellSet()) {
|
||||
sink(c.getValue());
|
||||
sink(c.getValue()); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
sink(t1.remove("r", "c"));
|
||||
sink(t1.remove("r", "c")); // $numTaintFlow=1
|
||||
|
||||
t3.row("r").put("c", x);
|
||||
sink(t3); // Not detected
|
||||
sink(t3); // $ MISSING:numTaintFlow=1
|
||||
}
|
||||
|
||||
void test4(Multimap<String, String> m1, Multimap<String, String> m2, Multimap<String, String> m3,
|
||||
Multimap<String, String> m4, Multimap<String, String> m5){
|
||||
String x = taint();
|
||||
m1.put("k", x);
|
||||
sink(m1);
|
||||
sink(m1.get("k"));
|
||||
sink(m1); // $numTaintFlow=1
|
||||
sink(m1.get("k")); // $numTaintFlow=1
|
||||
|
||||
m2.putAll("k", ImmutableList.of("a", x, "b"));
|
||||
sink(m2);
|
||||
sink(m2); // $numTaintFlow=1
|
||||
|
||||
m3.putAll(m1);
|
||||
sink(m3);
|
||||
sink(m3); // $numTaintFlow=1
|
||||
|
||||
m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a")));
|
||||
for (Map.Entry<String, String> e : m4.entries()) {
|
||||
sink(e.getValue());
|
||||
sink(e.getValue()); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
m5.asMap().get("k").add(x);
|
||||
sink(m5); // Not detected
|
||||
sink(m5); // $ MISSING:numTaintFlow=1
|
||||
}
|
||||
|
||||
void test5(Comparator<String> comp, SortedSet<String> sorS, SortedMap<String, String> sorM) {
|
||||
ImmutableSortedSet<String> s = ImmutableSortedSet.of(taint());
|
||||
|
||||
sink(s);
|
||||
sink(ImmutableSortedSet.copyOf(s));
|
||||
sink(ImmutableSortedSet.copyOf(comp, s));
|
||||
sink(s); // $numTaintFlow=1
|
||||
sink(ImmutableSortedSet.copyOf(s)); // $numTaintFlow=1
|
||||
sink(ImmutableSortedSet.copyOf(comp, s)); // $numTaintFlow=1
|
||||
|
||||
sorS.add(taint());
|
||||
sink(ImmutableSortedSet.copyOfSorted(sorS));
|
||||
sink(ImmutableSortedSet.copyOfSorted(sorS)); // $numTaintFlow=1
|
||||
|
||||
sink(ImmutableList.sortedCopyOf(s));
|
||||
sink(ImmutableList.sortedCopyOf(comp, s));
|
||||
sink(ImmutableList.sortedCopyOf(s)); // $numTaintFlow=1
|
||||
sink(ImmutableList.sortedCopyOf(comp, s)); // $numTaintFlow=1
|
||||
|
||||
ImmutableSortedMap<String, String> m = ImmutableSortedMap.of("k", taint());
|
||||
|
||||
sink(m);
|
||||
sink(ImmutableSortedMap.copyOf(m));
|
||||
sink(ImmutableSortedMap.copyOf(m, comp));
|
||||
sink(m); // $numTaintFlow=1
|
||||
sink(ImmutableSortedMap.copyOf(m)); // $numTaintFlow=1
|
||||
sink(ImmutableSortedMap.copyOf(m, comp)); // $numTaintFlow=1
|
||||
|
||||
sorM.put("k", taint());
|
||||
sink(ImmutableSortedMap.copyOfSorted(sorM));
|
||||
sink(ImmutableSortedMap.copyOfSorted(sorM)); // $numTaintFlow=1
|
||||
}
|
||||
}
|
||||
126
java/ql/test/library-tests/frameworks/guava/TestIO.java
Normal file
126
java/ql/test/library-tests/frameworks/guava/TestIO.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.google.common.io;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.StringBuffer;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Closeable;
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
|
||||
class TestIO {
|
||||
Object taint() { return null; }
|
||||
String staint(){ return (String) taint(); }
|
||||
byte[] btaint() { return (byte[]) taint(); }
|
||||
InputStream itaint() { return (InputStream) taint(); }
|
||||
Reader rtaint() { return new InputStreamReader(itaint()); }
|
||||
Path ptaint() { return (Path) taint(); }
|
||||
|
||||
void sink(Object o) {}
|
||||
|
||||
void test1() {
|
||||
BaseEncoding enc = BaseEncoding.base64();
|
||||
sink(enc.decode(staint())); // $numTaintFlow=1
|
||||
sink(enc.encode(btaint())); // $numTaintFlow=1
|
||||
sink(enc.encode(btaint(), 0, 42)); // $numTaintFlow=1
|
||||
sink(enc.decodingStream(rtaint())); // $numTaintFlow=1
|
||||
sink(enc.decodingSource(CharSource.wrap(staint()))); // $numTaintFlow=1
|
||||
sink(enc.withSeparator(staint(), 10).omitPadding().lowerCase().decode("abc")); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test2() throws IOException {
|
||||
ByteSource b = ByteSource.wrap(btaint());
|
||||
sink(b.openStream()); // $numTaintFlow=1
|
||||
sink(b.openBufferedStream()); // $numTaintFlow=1
|
||||
sink(b.asCharSource(null)); // $numTaintFlow=1
|
||||
sink(b.slice(42,1337)); // $numTaintFlow=1
|
||||
sink(b.read()); // $numTaintFlow=1
|
||||
sink(ByteSource.concat(ByteSource.empty(), ByteSource.empty(), b)); // $numTaintFlow=1
|
||||
sink(ByteSource.concat(ImmutableList.of(ByteSource.empty(), ByteSource.empty(), b))); // $numTaintFlow=1
|
||||
sink(b.read(new MyByteProcessor())); // $ MISSING:numTaintFlow=1
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
b.copyTo(out);
|
||||
sink(out.toByteArray()); // $numTaintFlow=1
|
||||
|
||||
CharSource c = CharSource.wrap(staint());
|
||||
sink(c.openStream()); // $numTaintFlow=1
|
||||
sink(c.openBufferedStream()); // $numTaintFlow=1
|
||||
sink(c.asByteSource(null)); // $numTaintFlow=1
|
||||
sink(c.readFirstLine()); // $numTaintFlow=1
|
||||
sink(c.readLines()); // $numTaintFlow=1
|
||||
sink(c.read()); // $numTaintFlow=1
|
||||
sink(c.lines()); // $numTaintFlow=1
|
||||
sink(CharSource.concat(CharSource.empty(), CharSource.empty(), c)); // $numTaintFlow=1
|
||||
sink(CharSource.concat(ImmutableList.of(CharSource.empty(), CharSource.empty(), c))); // $numTaintFlow=1
|
||||
sink(c.readLines(new MyLineProcessor())); // $ MISSING:numTaintFlow=1
|
||||
c.forEachLine(l -> sink(l)); // $ MISSING:numTaintFlow=1
|
||||
StringBuffer buf = new StringBuffer();
|
||||
c.copyTo(buf);
|
||||
sink(buf); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
class MyByteProcessor implements ByteProcessor<Object> {
|
||||
byte[] buf;
|
||||
public Object getResult() { return buf; }
|
||||
public boolean processBytes(byte[] b, int off, int len) { this.buf = b; return false; }
|
||||
}
|
||||
|
||||
class MyLineProcessor implements LineProcessor<String> {
|
||||
String s = "";
|
||||
public String getResult() { return s; }
|
||||
public boolean processLine(String l) { this.s += l; return true; }
|
||||
}
|
||||
|
||||
void test3() throws IOException {
|
||||
sink(ByteStreams.limit(itaint(), 1337)); // $numTaintFlow=1
|
||||
sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1
|
||||
sink(ByteStreams.newDataInput(btaint(), 0)); // $numTaintFlow=1
|
||||
sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1
|
||||
sink(ByteStreams.newDataInput(btaint()).readLine()); // $ MISSING:numTaintFlow=1
|
||||
sink(ByteStreams.newDataInput(new ByteArrayInputStream(btaint()))); // $numTaintFlow=1
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write(btaint());
|
||||
sink(ByteStreams.newDataOutput(out)); // $numTaintFlow=1
|
||||
byte[] b1 = null, b2 = null, b3 = null;
|
||||
ByteStreams.read(itaint(), b1, 0, 42);
|
||||
sink(b1); // $numTaintFlow=1
|
||||
ByteStreams.readFully(itaint(), b2);
|
||||
sink(b2); // $numTaintFlow=1
|
||||
ByteStreams.readFully(itaint(), b3, 0, 42);
|
||||
sink(b3); // $numTaintFlow=1
|
||||
sink(ByteStreams.readBytes(itaint(), new MyByteProcessor())); // $ MISSING:numTaintFlow=1
|
||||
sink(ByteStreams.toByteArray(itaint())); // $numTaintFlow=1
|
||||
ByteArrayDataOutput out2 = ByteStreams.newDataOutput();
|
||||
out2.writeUTF(staint());
|
||||
sink(out2.toByteArray()); // $numTaintFlow=1
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
CharStreams.copy(rtaint(), buf);
|
||||
sink(buf); // $numTaintFlow=1
|
||||
sink(CharStreams.readLines(rtaint())); // $numTaintFlow=1
|
||||
sink(CharStreams.readLines(rtaint(), new MyLineProcessor())); // $ MISSING:numTaintFlow=1
|
||||
sink(CharStreams.toString(rtaint())); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test4() throws IOException {
|
||||
sink(Closer.create().register((Closeable) taint())); // $numTaintFlow=1
|
||||
sink(new LineReader(rtaint()).readLine()); // $numTaintFlow=1
|
||||
sink(Files.simplifyPath(staint())); // $numTaintFlow=1
|
||||
sink(Files.getFileExtension(staint())); // $numTaintFlow=1
|
||||
sink(Files.getNameWithoutExtension(staint())); // $numTaintFlow=1
|
||||
sink(MoreFiles.getFileExtension(ptaint())); // $numTaintFlow=1
|
||||
sink(MoreFiles.getNameWithoutExtension(ptaint())); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test6() throws IOException {
|
||||
sink(new CountingInputStream(itaint())); // $numTaintFlow=1
|
||||
byte[] buf = null;
|
||||
new CountingInputStream(itaint()).read(buf, 0, 42);
|
||||
sink(buf); // $numTaintFlow=1
|
||||
sink(new LittleEndianDataInputStream(itaint())); // $numTaintFlow=1
|
||||
sink(new LittleEndianDataInputStream(itaint()).readUTF()); // $ MISSING:numTaintFlow=1
|
||||
}
|
||||
}
|
||||
@@ -14,14 +14,14 @@ class TestStrings {
|
||||
void test1() {
|
||||
String x = taint();
|
||||
|
||||
sink(Strings.padStart(x, 10, ' '));
|
||||
sink(Strings.padEnd(x, 10, ' '));
|
||||
sink(Strings.repeat(x, 3));
|
||||
sink(Strings.emptyToNull(Strings.nullToEmpty(x)));
|
||||
sink(Strings.lenientFormat(x, 3));
|
||||
sink(Strings.commonPrefix(x, "abc"));
|
||||
sink(Strings.commonSuffix(x, "cde"));
|
||||
sink(Strings.lenientFormat("%s = %s", x, 3));
|
||||
sink(Strings.padStart(x, 10, ' ')); // $numTaintFlow=1
|
||||
sink(Strings.padEnd(x, 10, ' ')); // $numTaintFlow=1
|
||||
sink(Strings.repeat(x, 3)); // $numTaintFlow=1
|
||||
sink(Strings.emptyToNull(Strings.nullToEmpty(x))); // $numTaintFlow=1
|
||||
sink(Strings.lenientFormat(x, 3)); // $numTaintFlow=1
|
||||
sink(Strings.commonPrefix(x, "abc"));
|
||||
sink(Strings.commonSuffix(x, "cde"));
|
||||
sink(Strings.lenientFormat("%s = %s", x, 3)); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test2() {
|
||||
@@ -29,10 +29,10 @@ class TestStrings {
|
||||
Splitter s = Splitter.on(x).omitEmptyStrings();
|
||||
|
||||
sink(s.split("x y z"));
|
||||
sink(s.split(x));
|
||||
sink(s.splitToList(x));
|
||||
sink(s.split(x)); // $numTaintFlow=1
|
||||
sink(s.splitToList(x)); // $numTaintFlow=1
|
||||
sink(s.withKeyValueSeparator("=").split("a=b"));
|
||||
sink(s.withKeyValueSeparator("=").split(x));
|
||||
sink(s.withKeyValueSeparator("=").split(x)); // $numTaintFlow=1
|
||||
}
|
||||
|
||||
void test3() {
|
||||
@@ -43,20 +43,20 @@ class TestStrings {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sink(safeJoiner.appendTo(sb, "a", "b", "c"));
|
||||
sink(sb.toString());
|
||||
sink(taintedJoiner.appendTo(sb, "a", "b", "c"));
|
||||
sink(sb.toString());
|
||||
sink(safeJoiner.appendTo(sb, "a", "b", "c"));
|
||||
sink(sb.toString());
|
||||
sink(taintedJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1
|
||||
sink(sb.toString()); // $numTaintFlow=1
|
||||
sink(safeJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1
|
||||
sink(sb.toString()); // $numTaintFlow=1
|
||||
|
||||
sb = new StringBuilder();
|
||||
sink(safeJoiner.appendTo(sb, x, x));
|
||||
sink(safeJoiner.appendTo(sb, x, x)); // $numTaintFlow=1
|
||||
|
||||
Map<String, String> m = new HashMap<String, String>();
|
||||
m.put("k", "v");
|
||||
sink(safeJoiner.withKeyValueSeparator("=").join(m));
|
||||
sink(safeJoiner.withKeyValueSeparator(x).join(m));
|
||||
sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m));
|
||||
sink(safeJoiner.withKeyValueSeparator(x).join(m)); // $numTaintFlow=1
|
||||
sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m)); // $numTaintFlow=1
|
||||
m.put("k2", x);
|
||||
sink(safeJoiner.withKeyValueSeparator("=").join(m));
|
||||
sink(safeJoiner.withKeyValueSeparator("=").join(m)); // $numTaintFlow=1
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:17:14:17:24 | asList(...) |
|
||||
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:21:14:21:55 | filter(...) |
|
||||
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:23:14:23:51 | newHashSet(...) |
|
||||
| TestCollect.java:27:31:27:37 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
|
||||
| TestCollect.java:27:40:27:46 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
|
||||
| TestCollect.java:27:49:27:55 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
|
||||
| TestCollect.java:27:58:27:64 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
|
||||
| TestCollect.java:28:39:28:45 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
|
||||
| TestCollect.java:28:57:28:63 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
|
||||
| TestCollect.java:29:44:29:50 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
|
||||
| TestCollect.java:29:62:29:68 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
|
||||
| TestCollect.java:30:49:30:55 | taint(...) | TestCollect.java:30:14:30:56 | of(...) |
|
||||
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:41:14:41:22 | build(...) |
|
||||
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:46:14:46:22 | build(...) |
|
||||
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:48:14:48:60 | build(...) |
|
||||
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:54:14:54:23 | build(...) |
|
||||
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:64:14:64:15 | t1 |
|
||||
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:65:14:65:24 | row(...) |
|
||||
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:69:18:69:29 | getValue(...) |
|
||||
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:72:14:72:32 | remove(...) |
|
||||
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:82:14:82:15 | m1 |
|
||||
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:83:14:83:24 | get(...) |
|
||||
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:86:14:86:15 | m2 |
|
||||
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:89:14:89:15 | m3 |
|
||||
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:93:18:93:29 | getValue(...) |
|
||||
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:103:14:103:14 | s |
|
||||
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:104:14:104:41 | copyOf(...) |
|
||||
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:105:14:105:47 | copyOf(...) |
|
||||
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:110:14:110:42 | sortedCopyOf(...) |
|
||||
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:111:14:111:48 | sortedCopyOf(...) |
|
||||
| TestCollect.java:107:18:107:24 | taint(...) | TestCollect.java:108:14:108:50 | copyOfSorted(...) |
|
||||
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:115:14:115:14 | m |
|
||||
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:116:14:116:41 | copyOf(...) |
|
||||
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:117:14:117:47 | copyOf(...) |
|
||||
| TestCollect.java:119:23:119:29 | taint(...) | TestCollect.java:120:14:120:50 | copyOfSorted(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:17:14:17:41 | padStart(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:18:14:18:39 | padEnd(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:19:14:19:33 | repeat(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:20:14:20:56 | emptyToNull(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:21:14:21:40 | lenientFormat(...) |
|
||||
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:24:14:24:51 | lenientFormat(...) |
|
||||
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:32:14:32:23 | split(...) |
|
||||
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:33:14:33:29 | splitToList(...) |
|
||||
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:35:14:35:50 | split(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:46:14:46:54 | appendTo(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:47:14:47:26 | toString(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:48:14:48:51 | appendTo(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:49:14:49:26 | toString(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:52:14:52:42 | appendTo(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:57:14:57:56 | join(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:58:14:58:82 | join(...) |
|
||||
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:60:14:60:58 | join(...) |
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class Conf extends TaintTracking::Configuration {
|
||||
Conf() { this = "qltest:frameworks:guava" }
|
||||
@@ -13,6 +14,18 @@ class Conf extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::Node src, DataFlow::Node sink, Conf conf
|
||||
where conf.hasFlow(src, sink)
|
||||
select src, sink
|
||||
class HasFlowTest extends InlineExpectationsTest {
|
||||
HasFlowTest() { this = "HasFlowTest" }
|
||||
|
||||
override string getARelevantTag() { result = "numTaintFlow" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "numTaintFlow" and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, Conf conf, int num | conf.hasFlow(src, sink) |
|
||||
value = num.toString() and
|
||||
sink.getLocation() = location and
|
||||
element = sink.toString() and
|
||||
num = strictcount(DataFlow::Node src2 | conf.hasFlow(src2, sink))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.commons.lang3;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class RegExUtils {
|
||||
public static String removeAll(final String text, final Pattern regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String removeAll(final String text, final String regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String removeFirst(final String text, final Pattern regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String removeFirst(final String text, final String regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String removePattern(final String text, final String regex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replaceAll(final String text, final Pattern regex, final String replacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replaceAll(final String text, final String regex, final String replacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replaceFirst(final String text, final Pattern regex, final String replacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replaceFirst(final String text, final String regex, final String replacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replacePattern(final String text, final String regex, final String replacement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.base;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public interface Function<F, T> extends java.util.function.Function<F, T> {
|
||||
@Override
|
||||
T apply(@Nullable F input);
|
||||
|
||||
@Override
|
||||
boolean equals(@Nullable Object object);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.base;
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class Optional<T> implements Serializable {
|
||||
public static <T> Optional<T> absent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> Optional<T> of(T reference) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> @Nullable Optional<T> fromJavaUtil(
|
||||
java.util.Optional<T> javaUtilOptional) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> java.util.Optional<T> toJavaUtil(
|
||||
@Nullable Optional<T> googleOptional) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.util.Optional<T> toJavaUtil() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract boolean isPresent();
|
||||
|
||||
public abstract T get();
|
||||
|
||||
public abstract T or(T defaultValue);
|
||||
|
||||
public abstract Optional<T> or(Optional<? extends T> secondChoice);
|
||||
|
||||
public abstract T or(Supplier<? extends T> supplier);
|
||||
|
||||
public abstract @Nullable T orNull();
|
||||
|
||||
public abstract Set<T> asSet();
|
||||
|
||||
public abstract <V> Optional<V> transform(Function<? super T, V> function);
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(@Nullable Object object);
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
public static <T> Iterable<T> presentInstances(
|
||||
final Iterable<? extends Optional<? extends T>> optionals) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.base;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public interface Predicate<T> extends java.util.function.Predicate<T> {
|
||||
boolean apply(@Nullable T input);
|
||||
|
||||
@Override
|
||||
boolean equals(@Nullable Object object);
|
||||
|
||||
@Override
|
||||
default boolean test(@Nullable T input) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.base;
|
||||
|
||||
public interface Supplier<T> extends java.util.function.Supplier<T> {
|
||||
@Override
|
||||
T get();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.common.graph;
|
||||
|
||||
public interface SuccessorsFunction<N> {
|
||||
Iterable<? extends N> successors(N node);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.common.graph;
|
||||
|
||||
public abstract class Traverser<N> {
|
||||
public static <N> Traverser<N> forGraph(final SuccessorsFunction<N> graph) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <N> Traverser<N> forTree(final SuccessorsFunction<N> tree) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> breadthFirst(N startNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> breadthFirst(Iterable<? extends N> startNodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> depthFirstPreOrder(N startNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> depthFirstPreOrder(Iterable<? extends N> startNodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> depthFirstPostOrder(N startNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final Iterable<N> depthFirstPostOrder(Iterable<? extends N> startNodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.hash;
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface Funnel<T> extends Serializable {
|
||||
void funnel(T from, PrimitiveSink into);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.hash;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class HashCode {
|
||||
public abstract int bits();
|
||||
|
||||
public abstract int asInt();
|
||||
|
||||
public abstract long asLong();
|
||||
|
||||
public abstract long padToLong();
|
||||
|
||||
public abstract byte[] asBytes();
|
||||
|
||||
public int writeBytesTo(byte[] dest, int offset, int maxLength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static HashCode fromInt(int hash) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashCode fromLong(long hash) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashCode fromBytes(byte[] bytes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashCode fromString(String string) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(@Nullable Object object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.hash;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public interface HashFunction {
|
||||
Hasher newHasher();
|
||||
|
||||
Hasher newHasher(int expectedInputSize);
|
||||
|
||||
HashCode hashInt(int input);
|
||||
|
||||
HashCode hashLong(long input);
|
||||
|
||||
HashCode hashBytes(byte[] input);
|
||||
|
||||
HashCode hashBytes(byte[] input, int off, int len);
|
||||
|
||||
HashCode hashBytes(ByteBuffer input);
|
||||
|
||||
HashCode hashUnencodedChars(CharSequence input);
|
||||
|
||||
HashCode hashString(CharSequence input, Charset charset);
|
||||
|
||||
<T> HashCode hashObject(T instance, Funnel<? super T> funnel);
|
||||
|
||||
int bits();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.hash;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public interface Hasher extends PrimitiveSink {
|
||||
@Override
|
||||
Hasher putByte(byte b);
|
||||
|
||||
@Override
|
||||
Hasher putBytes(byte[] bytes);
|
||||
|
||||
@Override
|
||||
Hasher putBytes(byte[] bytes, int off, int len);
|
||||
|
||||
@Override
|
||||
Hasher putBytes(ByteBuffer bytes);
|
||||
|
||||
@Override
|
||||
Hasher putShort(short s);
|
||||
|
||||
@Override
|
||||
Hasher putInt(int i);
|
||||
|
||||
@Override
|
||||
Hasher putLong(long l);
|
||||
|
||||
@Override
|
||||
Hasher putFloat(float f);
|
||||
|
||||
@Override
|
||||
Hasher putDouble(double d);
|
||||
|
||||
@Override
|
||||
Hasher putBoolean(boolean b);
|
||||
|
||||
@Override
|
||||
Hasher putChar(char c);
|
||||
|
||||
@Override
|
||||
Hasher putUnencodedChars(CharSequence charSequence);
|
||||
|
||||
@Override
|
||||
Hasher putString(CharSequence charSequence, Charset charset);
|
||||
|
||||
<T> Hasher putObject(T instance, Funnel<? super T> funnel);
|
||||
|
||||
HashCode hash();
|
||||
|
||||
@Override
|
||||
int hashCode();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.hash;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public interface PrimitiveSink {
|
||||
PrimitiveSink putByte(byte b);
|
||||
|
||||
PrimitiveSink putBytes(byte[] bytes);
|
||||
|
||||
PrimitiveSink putBytes(byte[] bytes, int off, int len);
|
||||
|
||||
PrimitiveSink putBytes(ByteBuffer bytes);
|
||||
|
||||
PrimitiveSink putShort(short s);
|
||||
|
||||
PrimitiveSink putInt(int i);
|
||||
|
||||
PrimitiveSink putLong(long l);
|
||||
|
||||
PrimitiveSink putFloat(float f);
|
||||
|
||||
PrimitiveSink putDouble(double d);
|
||||
|
||||
PrimitiveSink putBoolean(boolean b);
|
||||
|
||||
PrimitiveSink putChar(char c);
|
||||
|
||||
PrimitiveSink putUnencodedChars(CharSequence charSequence);
|
||||
|
||||
PrimitiveSink putString(CharSequence charSequence, Charset charset);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
public abstract class BaseEncoding {
|
||||
public static final class DecodingException extends IOException {
|
||||
}
|
||||
public String encode(byte[] bytes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final String encode(byte[] bytes, int off, int len) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract OutputStream encodingStream(Writer writer);
|
||||
|
||||
public final ByteSink encodingSink(final CharSink encodedSink) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract boolean canDecode(CharSequence chars);
|
||||
|
||||
public final byte[] decode(CharSequence chars) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract InputStream decodingStream(Reader reader);
|
||||
|
||||
public final ByteSource decodingSource(final CharSource encodedSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract BaseEncoding omitPadding();
|
||||
|
||||
public abstract BaseEncoding withPadChar(char padChar);
|
||||
|
||||
public abstract BaseEncoding withSeparator(String separator, int n);
|
||||
|
||||
public abstract BaseEncoding upperCase();
|
||||
|
||||
public abstract BaseEncoding lowerCase();
|
||||
|
||||
public static BaseEncoding base64() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseEncoding base64Url() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseEncoding base32() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseEncoding base32Hex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BaseEncoding base16() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.DataInput;
|
||||
|
||||
public interface ByteArrayDataInput extends DataInput {
|
||||
@Override
|
||||
void readFully(byte b[]);
|
||||
|
||||
@Override
|
||||
void readFully(byte b[], int off, int len);
|
||||
|
||||
@Override
|
||||
int skipBytes(int n);
|
||||
|
||||
@Override
|
||||
boolean readBoolean();
|
||||
|
||||
@Override
|
||||
byte readByte();
|
||||
|
||||
@Override
|
||||
int readUnsignedByte();
|
||||
|
||||
@Override
|
||||
short readShort();
|
||||
|
||||
@Override
|
||||
int readUnsignedShort();
|
||||
|
||||
@Override
|
||||
char readChar();
|
||||
|
||||
@Override
|
||||
int readInt();
|
||||
|
||||
@Override
|
||||
long readLong();
|
||||
|
||||
@Override
|
||||
float readFloat();
|
||||
|
||||
@Override
|
||||
double readDouble();
|
||||
|
||||
@Override
|
||||
String readLine();
|
||||
|
||||
@Override
|
||||
String readUTF();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.DataOutput;
|
||||
|
||||
public interface ByteArrayDataOutput extends DataOutput {
|
||||
@Override
|
||||
void write(int b);
|
||||
|
||||
@Override
|
||||
void write(byte b[]);
|
||||
|
||||
@Override
|
||||
void write(byte b[], int off, int len);
|
||||
|
||||
@Override
|
||||
void writeBoolean(boolean v);
|
||||
|
||||
@Override
|
||||
void writeByte(int v);
|
||||
|
||||
@Override
|
||||
void writeShort(int v);
|
||||
|
||||
@Override
|
||||
void writeChar(int v);
|
||||
|
||||
@Override
|
||||
void writeInt(int v);
|
||||
|
||||
@Override
|
||||
void writeLong(long v);
|
||||
|
||||
@Override
|
||||
void writeFloat(float v);
|
||||
|
||||
@Override
|
||||
void writeDouble(double v);
|
||||
|
||||
@Override
|
||||
void writeChars(String s);
|
||||
|
||||
@Override
|
||||
void writeUTF(String s);
|
||||
|
||||
@Override
|
||||
void writeBytes(String s);
|
||||
|
||||
byte[] toByteArray();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface ByteProcessor<T> {
|
||||
boolean processBytes(byte[] buf, int off, int len) throws IOException;
|
||||
|
||||
T getResult();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public abstract class ByteSink {
|
||||
public CharSink asCharSink(Charset charset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract OutputStream openStream() throws IOException;
|
||||
|
||||
public OutputStream openBufferedStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void write(byte[] bytes) throws IOException {
|
||||
}
|
||||
|
||||
public long writeFrom(InputStream input) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.hash.HashCode;
|
||||
import com.google.common.hash.HashFunction;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
|
||||
public abstract class ByteSource {
|
||||
public CharSource asCharSource(Charset charset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract InputStream openStream() throws IOException;
|
||||
|
||||
public InputStream openBufferedStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ByteSource slice(long offset, long length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isEmpty() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Optional<Long> sizeIfKnown() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long size() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long copyTo(OutputStream output) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long copyTo(ByteSink sink) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] read() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T read(ByteProcessor<T> processor) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HashCode hash(HashFunction hashFunction) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean contentEquals(ByteSource other) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ByteSource concat(Iterable<? extends ByteSource> sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSource concat(Iterator<? extends ByteSource> sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSource concat(ByteSource... sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSource wrap(byte[] b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSource empty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
|
||||
public final class ByteStreams {
|
||||
public static long copy(InputStream from, OutputStream to) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static long copy(ReadableByteChannel from, WritableByteChannel to) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(InputStream in) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long exhaust(InputStream in) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static ByteArrayDataInput newDataInput(byte[] bytes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteArrayDataInput newDataInput(byte[] bytes, int start) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteArrayDataInput newDataInput(ByteArrayInputStream byteArrayInputStream) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteArrayDataOutput newDataOutput() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteArrayDataOutput newDataOutput(int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputStream) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static OutputStream nullOutputStream() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static InputStream limit(InputStream in, long limit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void readFully(InputStream in, byte[] b) throws IOException {
|
||||
}
|
||||
|
||||
public static void readFully(InputStream in, byte[] b, int off, int len) throws IOException {
|
||||
}
|
||||
|
||||
public static void skipFully(InputStream in, long n) throws IOException {
|
||||
}
|
||||
|
||||
public static <T> T readBytes(InputStream input, ByteProcessor<T> processor) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int read(InputStream in, byte[] b, int off, int len) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class CharSink {
|
||||
public abstract Writer openStream() throws IOException;
|
||||
|
||||
public Writer openBufferedStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void write(CharSequence charSequence) throws IOException {
|
||||
}
|
||||
|
||||
public void writeLines(Iterable<? extends CharSequence> lines) throws IOException {
|
||||
}
|
||||
|
||||
public void writeLines(Iterable<? extends CharSequence> lines, String lineSeparator)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
public void writeLines(Stream<? extends CharSequence> lines) throws IOException {
|
||||
}
|
||||
|
||||
public void writeLines(Stream<? extends CharSequence> lines, String lineSeparator)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
public long writeFrom(Readable readable) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class CharSource {
|
||||
public ByteSource asByteSource(Charset charset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract Reader openStream() throws IOException;
|
||||
|
||||
public BufferedReader openBufferedStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream<String> lines() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Optional<Long> lengthIfKnown() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long length() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long copyTo(Appendable appendable) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long copyTo(CharSink sink) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String read() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable String readFirstLine() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImmutableList<String> readLines() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T readLines(LineProcessor<T> processor) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void forEachLine(Consumer<? super String> action) throws IOException {
|
||||
}
|
||||
|
||||
public boolean isEmpty() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static CharSource concat(Iterable<? extends CharSource> sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource concat(Iterator<? extends CharSource> sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource concat(CharSource... sources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource wrap(CharSequence charSequence) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource empty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
|
||||
public final class CharStreams {
|
||||
public static long copy(Readable from, Appendable to) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static String toString(Readable r) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> readLines(Readable r) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> T readLines(Readable readable, LineProcessor<T> processor) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long exhaust(Readable readable) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void skipFully(Reader reader, long n) throws IOException {
|
||||
}
|
||||
|
||||
public static Writer nullWriter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Writer asWriter(Appendable target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class Closer implements Closeable {
|
||||
public static Closer create() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <C extends Closeable> C register(@Nullable C closeable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public RuntimeException rethrow(Throwable e) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <X extends Exception> RuntimeException rethrow(Throwable e, Class<X> declaredType)
|
||||
throws IOException, X {
|
||||
return null;
|
||||
}
|
||||
|
||||
public <X1 extends Exception, X2 extends Exception> RuntimeException rethrow(
|
||||
Throwable e, Class<X1> declaredType1, Class<X2> declaredType2) throws IOException, X1, X2 {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public final class CountingInputStream extends FilterInputStream {
|
||||
public CountingInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mark(int readlimit) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
|
||||
public enum FileWriteMode {
|
||||
}
|
||||
131
java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java
Normal file
131
java/ql/test/stubs/guava-30.0/com/google/common/io/Files.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.graph.Traverser;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel.MapMode;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
public final class Files {
|
||||
public static BufferedReader newReader(File file, Charset charset) throws FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BufferedWriter newWriter(File file, Charset charset) throws FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSource asByteSource(File file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSink asByteSink(File file, FileWriteMode... modes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource asCharSource(File file, Charset charset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSink asCharSink(File file, Charset charset, FileWriteMode... modes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(File file) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String toString(File file, Charset charset) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void write(byte[] from, File to) throws IOException {
|
||||
}
|
||||
|
||||
public static void write(CharSequence from, File to, Charset charset) throws IOException {
|
||||
}
|
||||
|
||||
public static void copy(File from, OutputStream to) throws IOException {
|
||||
}
|
||||
|
||||
public static void copy(File from, File to) throws IOException {
|
||||
}
|
||||
|
||||
public static boolean equal(File file1, File file2) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static File createTempDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void touch(File file) throws IOException {
|
||||
}
|
||||
|
||||
public static void createParentDirs(File file) throws IOException {
|
||||
}
|
||||
|
||||
public static void move(File from, File to) throws IOException {
|
||||
}
|
||||
|
||||
public static List<String> readLines(File file, Charset charset) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MappedByteBuffer map(File file) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MappedByteBuffer map(File file, MapMode mode) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MappedByteBuffer map(File file, MapMode mode, long size) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String simplifyPath(String pathname) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getFileExtension(String fullName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getNameWithoutExtension(String file) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Traverser<File> fileTraverser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Predicate<File> isDirectory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Predicate<File> isFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface LineProcessor<T> {
|
||||
boolean processLine(String line) throws IOException;
|
||||
|
||||
T getResult();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.IOException;
|
||||
|
||||
public final class LineReader {
|
||||
public LineReader(Readable readable) {
|
||||
}
|
||||
|
||||
public String readLine() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import java.io.DataInput;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public final class LittleEndianDataInputStream extends FilterInputStream implements DataInput {
|
||||
public LittleEndianDataInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLine() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte[] b) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(byte[] b, int off, int len) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skipBytes(int n) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readUTF() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() throws IOException {
|
||||
return '0';
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.graph.Traverser;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
|
||||
public final class MoreFiles {
|
||||
public static ByteSource asByteSource(Path path, OpenOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ByteSink asByteSink(Path path, OpenOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSource asCharSource(Path path, Charset charset, OpenOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CharSink asCharSink(Path path, Charset charset, OpenOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ImmutableList<Path> listFiles(Path dir) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Traverser<Path> fileTraverser() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Predicate<Path> isDirectory(LinkOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Predicate<Path> isRegularFile(LinkOption... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean equal(Path path1, Path path2) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void touch(Path path) throws IOException {
|
||||
}
|
||||
|
||||
public static void createParentDirectories(Path path, FileAttribute<?>... attrs)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
public static String getFileExtension(Path path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getNameWithoutExtension(Path path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void deleteRecursively(Path path, RecursiveDeleteOption... options)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
public static void deleteDirectoryContents(Path path, RecursiveDeleteOption... options)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.common.io;
|
||||
|
||||
public enum RecursiveDeleteOption {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
package org.checkerframework.checker.nullness.qual;
|
||||
public @interface Nullable {}
|
||||
@@ -43,7 +43,7 @@ public class Main {
|
||||
* A version identifier that should be updated every time the extractor changes in such a way that
|
||||
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2021-02-24";
|
||||
public static final String EXTRACTOR_VERSION = "2021-03-08";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
|
||||
@@ -282,11 +282,18 @@ public class RegExpParser {
|
||||
if (this.match("+")) return this.finishTerm(new Plus(loc, atom, !this.match("?")));
|
||||
if (this.match("?")) return this.finishTerm(new Opt(loc, atom, !this.match("?")));
|
||||
if (this.match("{")) {
|
||||
Double lo = toNumber(this.readDigits(false)), hi;
|
||||
String matched = "{"; // keeping track of the string matched so far, in case this turns out not to be a quantifier.
|
||||
String digits = this.readDigits(false);
|
||||
matched += digits;
|
||||
Double lo = toNumber(digits), hi;
|
||||
int prevPos = this.pos;
|
||||
if (this.match(",")) {
|
||||
matched += ",";
|
||||
if (!this.lookahead("}")) {
|
||||
// atom{lo, hi}
|
||||
hi = toNumber(this.readDigits(false));
|
||||
digits = this.readDigits(false);
|
||||
matched += digits;
|
||||
hi = toNumber(digits);
|
||||
} else {
|
||||
// atom{lo,}
|
||||
hi = null;
|
||||
@@ -295,7 +302,11 @@ public class RegExpParser {
|
||||
// atom{lo}
|
||||
hi = lo;
|
||||
}
|
||||
this.expectRBrace();
|
||||
if (!this.match("}")) {
|
||||
// Not a quantifier, just parsing it as a constant.
|
||||
// E.g. a Regexp such as `/a{|X/`, where there is no matching `}`.
|
||||
return this.finishTerm(new Sequence(loc, Arrays.asList(atom, new Constant(loc, matched))));
|
||||
}
|
||||
return this.finishTerm(new Range(loc, atom, !this.match("?"), lo, hi));
|
||||
}
|
||||
return atom;
|
||||
|
||||
@@ -1666,13 +1666,10 @@ enclosing_stmt(#20541,#20540)
|
||||
enclosing_stmt(#20541,#20540)
|
||||
expr_containers(#20541,#20001)
|
||||
literals("/a{/","/a{/",#20541)
|
||||
#20542=*
|
||||
#20542=*
|
||||
regexpterm(#20542,1,#20541,0,"a{")
|
||||
#20543=@"loc,{#10000},37,2,37,3"
|
||||
locations_default(#20543,#10000,37,2,37,3)
|
||||
hasLocation(#20542,#20543)
|
||||
is_greedy(#20542)
|
||||
range_quantifier_lower_bound(#20542,0)
|
||||
hasLocation(#20542,#20543)
|
||||
#20544=*
|
||||
regexpterm(#20544,14,#20542,0,"a")
|
||||
@@ -1680,379 +1677,370 @@ locations_default(#20545,#10000,37,2,37,2)
|
||||
locations_default(#20545,#10000,37,2,37,2)
|
||||
hasLocation(#20544,#20545)
|
||||
regexp_const_value(#20544,"a")
|
||||
#20546=*
|
||||
regexp_parse_errors(#20546,#20542,"expected digit")
|
||||
#20547=@"loc,{#10000},37,4,37,4"
|
||||
locations_default(#20547,#10000,37,4,37,4)
|
||||
hasLocation(#20546,#20547)
|
||||
#20548=*
|
||||
regexp_parse_errors(#20548,#20542,"expected '}'")
|
||||
#20549=@"loc,{#10000},37,3,37,3"
|
||||
locations_default(#20549,#10000,37,3,37,3)
|
||||
#20546=*
|
||||
regexpterm(#20546,14,#20542,1,"a{")
|
||||
hasLocation(#20546,#20543)
|
||||
regexp_const_value(#20546,"{")
|
||||
#20547=*
|
||||
regexp_parse_errors(#20547,#20542,"expected digit")
|
||||
#20548=@"loc,{#10000},37,4,37,4"
|
||||
locations_default(#20548,#10000,37,4,37,4)
|
||||
hasLocation(#20547,#20548)
|
||||
#20549=*
|
||||
stmts(#20549,2,#20001,37,"/a{b}/;")
|
||||
hasLocation(#20549,#20077)
|
||||
stmt_containers(#20549,#20001)
|
||||
#20550=*
|
||||
stmts(#20550,2,#20001,37,"/a{b}/;")
|
||||
hasLocation(#20550,#20077)
|
||||
#20550=*
|
||||
exprs(#20550,5,#20549,0,"/a{b}/")
|
||||
hasLocation(#20550,#20239)
|
||||
enclosing_stmt(#20550,#20549)
|
||||
expr_containers(#20550,#20001)
|
||||
literals("/a{b}/","/a{b}/",#20550)
|
||||
#20551=*
|
||||
exprs(#20551,5,#20550,0,"/a{b}/")
|
||||
hasLocation(#20551,#20239)
|
||||
enclosing_stmt(#20551,#20550)
|
||||
expr_containers(#20551,#20001)
|
||||
literals("/a{b}/","/a{b}/",#20551)
|
||||
#20552=*
|
||||
regexpterm(#20552,1,#20551,0,"a{b}")
|
||||
#20553=@"loc,{#10000},38,2,38,5"
|
||||
locations_default(#20553,#10000,38,2,38,5)
|
||||
hasLocation(#20552,#20553)
|
||||
#20554=*
|
||||
regexpterm(#20554,11,#20552,0,"a{")
|
||||
#20555=@"loc,{#10000},38,2,38,3"
|
||||
locations_default(#20555,#10000,38,2,38,3)
|
||||
hasLocation(#20554,#20555)
|
||||
is_greedy(#20554)
|
||||
range_quantifier_lower_bound(#20554,0)
|
||||
range_quantifier_upper_bound(#20554,0)
|
||||
#20556=*
|
||||
regexpterm(#20556,14,#20554,0,"a")
|
||||
#20557=@"loc,{#10000},38,2,38,2"
|
||||
locations_default(#20557,#10000,38,2,38,2)
|
||||
hasLocation(#20556,#20557)
|
||||
#20551=*
|
||||
regexpterm(#20551,1,#20550,0,"a{b}")
|
||||
#20552=@"loc,{#10000},38,2,38,5"
|
||||
locations_default(#20552,#10000,38,2,38,5)
|
||||
hasLocation(#20551,#20552)
|
||||
#20553=*
|
||||
regexpterm(#20553,1,#20551,0,"a{")
|
||||
#20554=@"loc,{#10000},38,2,38,3"
|
||||
locations_default(#20554,#10000,38,2,38,3)
|
||||
hasLocation(#20553,#20554)
|
||||
#20555=*
|
||||
regexpterm(#20555,14,#20553,0,"a")
|
||||
#20556=@"loc,{#10000},38,2,38,2"
|
||||
locations_default(#20556,#10000,38,2,38,2)
|
||||
hasLocation(#20555,#20556)
|
||||
regexp_const_value(#20555,"a")
|
||||
#20557=*
|
||||
regexpterm(#20557,14,#20553,1,"a{")
|
||||
hasLocation(#20557,#20554)
|
||||
regexp_const_value(#20557,"{")
|
||||
#20558=*
|
||||
#20558=*
|
||||
regexpterm(#20558,14,#20551,1,"b")
|
||||
#20559=@"loc,{#10000},38,4,38,4"
|
||||
locations_default(#20559,#10000,38,4,38,4)
|
||||
hasLocation(#20558,#20559)
|
||||
regexp_const_value(#20558,"b")
|
||||
#20560=*
|
||||
#20560=*
|
||||
regexpterm(#20560,14,#20551,2,"}")
|
||||
#20561=@"loc,{#10000},38,5,38,5"
|
||||
locations_default(#20561,#10000,38,5,38,5)
|
||||
hasLocation(#20560,#20561)
|
||||
regexp_const_value(#20560,"}")
|
||||
#20562=*
|
||||
#20562=*
|
||||
regexp_parse_errors(#20562,#20551,"expected digit")
|
||||
hasLocation(#20562,#20559)
|
||||
#20563=*
|
||||
regexp_parse_errors(#20563,#20552,"expected '}'")
|
||||
#20564=@"loc,{#10000},38,3,38,3"
|
||||
locations_default(#20564,#10000,38,3,38,3)
|
||||
#20563=*
|
||||
regexp_parse_errors(#20563,#20551,"unexpected character")
|
||||
hasLocation(#20563,#20561)
|
||||
#20564=*
|
||||
stmts(#20564,2,#20001,38,"/a{2/;")
|
||||
hasLocation(#20564,#20079)
|
||||
stmt_containers(#20564,#20001)
|
||||
#20565=*
|
||||
regexp_parse_errors(#20565,#20552,"unexpected character")
|
||||
#20565=*
|
||||
exprs(#20565,5,#20564,0,"/a{2/")
|
||||
hasLocation(#20565,#20243)
|
||||
enclosing_stmt(#20565,#20564)
|
||||
expr_containers(#20565,#20001)
|
||||
literals("/a{2/","/a{2/",#20565)
|
||||
#20566=*
|
||||
stmts(#20566,2,#20001,38,"/a{2/;")
|
||||
hasLocation(#20566,#20079)
|
||||
stmt_containers(#20566,#20001)
|
||||
#20567=*
|
||||
exprs(#20567,5,#20566,0,"/a{2/")
|
||||
hasLocation(#20567,#20243)
|
||||
enclosing_stmt(#20567,#20566)
|
||||
expr_containers(#20567,#20001)
|
||||
#20566=*
|
||||
regexpterm(#20566,1,#20565,0,"a{2")
|
||||
#20567=@"loc,{#10000},39,2,39,4"
|
||||
locations_default(#20567,#10000,39,2,39,4)
|
||||
hasLocation(#20566,#20567)
|
||||
#20568=*
|
||||
regexpterm(#20568,11,#20567,0,"a{2")
|
||||
#20569=@"loc,{#10000},39,2,39,4"
|
||||
#20568=*
|
||||
regexpterm(#20568,14,#20566,0,"a")
|
||||
#20569=@"loc,{#10000},39,2,39,2"
|
||||
locations_default(#20569,#10000,39,2,39,2)
|
||||
hasLocation(#20568,#20569)
|
||||
is_greedy(#20568)
|
||||
range_quantifier_lower_bound(#20568,2)
|
||||
hasLocation(#20568,#20569)
|
||||
regexp_const_value(#20568,"a")
|
||||
#20570=*
|
||||
regexpterm(#20570,14,#20568,0,"a")
|
||||
#20571=@"loc,{#10000},39,2,39,2"
|
||||
locations_default(#20571,#10000,39,2,39,2)
|
||||
hasLocation(#20570,#20571)
|
||||
#20570=*
|
||||
regexpterm(#20570,14,#20566,1,"a{2")
|
||||
hasLocation(#20570,#20567)
|
||||
regexp_const_value(#20570,"{2")
|
||||
#20571=*
|
||||
stmts(#20571,2,#20001,39,"/\xa/;")
|
||||
hasLocation(#20571,#20081)
|
||||
stmt_containers(#20571,#20001)
|
||||
#20572=*
|
||||
regexp_parse_errors(#20572,#20568,"expected '}'")
|
||||
#20573=@"loc,{#10000},39,4,39,4"
|
||||
locations_default(#20573,#10000,39,4,39,4)
|
||||
hasLocation(#20572,#20573)
|
||||
#20574=*
|
||||
stmts(#20574,2,#20001,39,"/\xa/;")
|
||||
hasLocation(#20574,#20081)
|
||||
stmt_containers(#20574,#20001)
|
||||
#20575=*
|
||||
exprs(#20575,5,#20574,0,"/\xa/")
|
||||
hasLocation(#20575,#20247)
|
||||
enclosing_stmt(#20575,#20574)
|
||||
expr_containers(#20575,#20001)
|
||||
literals("/\xa/","/\xa/",#20575)
|
||||
#20576=*
|
||||
regexpterm(#20576,15,#20575,0,"\xa")
|
||||
#20577=@"loc,{#10000},40,2,40,4"
|
||||
locations_default(#20577,#10000,40,2,40,4)
|
||||
hasLocation(#20576,#20577)
|
||||
#20572=*
|
||||
exprs(#20572,5,#20571,0,"/\xa/")
|
||||
hasLocation(#20572,#20247)
|
||||
enclosing_stmt(#20572,#20571)
|
||||
expr_containers(#20572,#20001)
|
||||
literals("/\xa/","/\xa/",#20572)
|
||||
#20573=*
|
||||
regexpterm(#20573,15,#20572,0,"\xa")
|
||||
#20574=@"loc,{#10000},40,2,40,4"
|
||||
locations_default(#20574,#10000,40,2,40,4)
|
||||
hasLocation(#20573,#20574)
|
||||
regexp_const_value(#20573,"
|
||||
")
|
||||
#20575=*
|
||||
regexp_parse_errors(#20575,#20573,"unexpected end of regular expression")
|
||||
#20576=@"loc,{#10000},40,5,40,5"
|
||||
locations_default(#20576,#10000,40,5,40,5)
|
||||
hasLocation(#20575,#20576)
|
||||
#20577=*
|
||||
stmts(#20577,2,#20001,40,"/\c0/;")
|
||||
hasLocation(#20577,#20083)
|
||||
stmt_containers(#20577,#20001)
|
||||
#20578=*
|
||||
regexp_parse_errors(#20578,#20576,"unexpected end of regular expression")
|
||||
#20579=@"loc,{#10000},40,5,40,5"
|
||||
locations_default(#20579,#10000,40,5,40,5)
|
||||
hasLocation(#20578,#20579)
|
||||
#20580=*
|
||||
stmts(#20580,2,#20001,40,"/\c0/;")
|
||||
hasLocation(#20580,#20083)
|
||||
#20578=*
|
||||
exprs(#20578,5,#20577,0,"/\c0/")
|
||||
hasLocation(#20578,#20251)
|
||||
enclosing_stmt(#20578,#20577)
|
||||
expr_containers(#20578,#20001)
|
||||
literals("/\c0/","/\c0/",#20578)
|
||||
#20579=*
|
||||
regexpterm(#20579,19,#20578,0,"\c0")
|
||||
#20580=@"loc,{#10000},41,2,41,4"
|
||||
locations_default(#20580,#10000,41,2,41,4)
|
||||
hasLocation(#20579,#20580)
|
||||
regexp_const_value(#20579,"")
|
||||
#20581=*
|
||||
exprs(#20581,5,#20580,0,"/\c0/")
|
||||
hasLocation(#20581,#20251)
|
||||
enclosing_stmt(#20581,#20580)
|
||||
expr_containers(#20581,#20001)
|
||||
literals("/\c0/","/\c0/",#20581)
|
||||
#20582=*
|
||||
regexpterm(#20582,19,#20581,0,"\c0")
|
||||
#20583=@"loc,{#10000},41,2,41,4"
|
||||
locations_default(#20583,#10000,41,2,41,4)
|
||||
hasLocation(#20582,#20583)
|
||||
#20581=*
|
||||
regexp_parse_errors(#20581,#20579,"expected control letter")
|
||||
#20582=@"loc,{#10000},41,4,41,4"
|
||||
locations_default(#20582,#10000,41,4,41,4)
|
||||
hasLocation(#20581,#20582)
|
||||
#20583=*
|
||||
stmts(#20583,2,#20001,41,"/[]/;")
|
||||
hasLocation(#20583,#20085)
|
||||
stmt_containers(#20583,#20001)
|
||||
#20584=*
|
||||
regexp_parse_errors(#20584,#20582,"expected control letter")
|
||||
#20585=@"loc,{#10000},41,4,41,4"
|
||||
locations_default(#20585,#10000,41,4,41,4)
|
||||
hasLocation(#20584,#20585)
|
||||
#20586=*
|
||||
stmts(#20586,2,#20001,41,"/[]/;")
|
||||
hasLocation(#20586,#20085)
|
||||
#20584=*
|
||||
exprs(#20584,5,#20583,0,"/[]/")
|
||||
hasLocation(#20584,#20255)
|
||||
enclosing_stmt(#20584,#20583)
|
||||
expr_containers(#20584,#20001)
|
||||
literals("/[]/","/[]/",#20584)
|
||||
#20585=*
|
||||
regexpterm(#20585,23,#20584,0,"[]")
|
||||
#20586=@"loc,{#10000},42,2,42,3"
|
||||
locations_default(#20586,#10000,42,2,42,3)
|
||||
hasLocation(#20585,#20586)
|
||||
#20587=*
|
||||
exprs(#20587,5,#20586,0,"/[]/")
|
||||
hasLocation(#20587,#20255)
|
||||
enclosing_stmt(#20587,#20586)
|
||||
expr_containers(#20587,#20001)
|
||||
#20587=*
|
||||
stmts(#20587,2,#20001,42,"/[^]/;")
|
||||
hasLocation(#20587,#20087)
|
||||
stmt_containers(#20587,#20001)
|
||||
#20588=*
|
||||
regexpterm(#20588,23,#20587,0,"[]")
|
||||
#20589=@"loc,{#10000},42,2,42,3"
|
||||
locations_default(#20589,#10000,42,2,42,3)
|
||||
hasLocation(#20588,#20589)
|
||||
#20590=*
|
||||
stmts(#20590,2,#20001,42,"/[^]/;")
|
||||
hasLocation(#20590,#20087)
|
||||
#20588=*
|
||||
exprs(#20588,5,#20587,0,"/[^]/")
|
||||
hasLocation(#20588,#20259)
|
||||
enclosing_stmt(#20588,#20587)
|
||||
expr_containers(#20588,#20001)
|
||||
literals("/[^]/","/[^]/",#20588)
|
||||
#20589=*
|
||||
regexpterm(#20589,23,#20588,0,"[^]")
|
||||
#20590=@"loc,{#10000},43,2,43,4"
|
||||
locations_default(#20590,#10000,43,2,43,4)
|
||||
hasLocation(#20589,#20590)
|
||||
is_inverted(#20589)
|
||||
#20591=*
|
||||
exprs(#20591,5,#20590,0,"/[^]/")
|
||||
hasLocation(#20591,#20259)
|
||||
enclosing_stmt(#20591,#20590)
|
||||
expr_containers(#20591,#20001)
|
||||
#20591=*
|
||||
stmts(#20591,2,#20001,43,"/<tpl\b ... /tpl>/;")
|
||||
hasLocation(#20591,#20089)
|
||||
stmt_containers(#20591,#20001)
|
||||
#20592=*
|
||||
regexpterm(#20592,23,#20591,0,"[^]")
|
||||
#20593=@"loc,{#10000},43,2,43,4"
|
||||
locations_default(#20593,#10000,43,2,43,4)
|
||||
hasLocation(#20592,#20593)
|
||||
is_inverted(#20592)
|
||||
#20594=*
|
||||
stmts(#20594,2,#20001,43,"/<tpl\b ... /tpl>/;")
|
||||
hasLocation(#20594,#20089)
|
||||
#20592=*
|
||||
exprs(#20592,5,#20591,0,"/<tpl\b ... \/tpl>/")
|
||||
hasLocation(#20592,#20263)
|
||||
enclosing_stmt(#20592,#20591)
|
||||
expr_containers(#20592,#20001)
|
||||
literals("/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/","/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/",#20592)
|
||||
#20593=*
|
||||
regexpterm(#20593,1,#20592,0,"<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>")
|
||||
#20594=@"loc,{#10000},44,2,44,58"
|
||||
locations_default(#20594,#10000,44,2,44,58)
|
||||
hasLocation(#20593,#20594)
|
||||
#20595=*
|
||||
exprs(#20595,5,#20594,0,"/<tpl\b ... \/tpl>/")
|
||||
hasLocation(#20595,#20263)
|
||||
enclosing_stmt(#20595,#20594)
|
||||
expr_containers(#20595,#20001)
|
||||
literals("/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/","/<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/",#20595)
|
||||
#20596=*
|
||||
regexpterm(#20596,1,#20595,0,"<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>")
|
||||
#20597=@"loc,{#10000},44,2,44,58"
|
||||
locations_default(#20597,#10000,44,2,44,58)
|
||||
hasLocation(#20596,#20597)
|
||||
#20598=*
|
||||
regexpterm(#20598,14,#20596,0,"<tpl")
|
||||
#20599=@"loc,{#10000},44,2,44,5"
|
||||
locations_default(#20599,#10000,44,2,44,5)
|
||||
hasLocation(#20598,#20599)
|
||||
regexp_const_value(#20598,"<tpl")
|
||||
#20600=*
|
||||
regexpterm(#20600,4,#20596,1,"\b")
|
||||
#20601=@"loc,{#10000},44,6,44,7"
|
||||
locations_default(#20601,#10000,44,6,44,7)
|
||||
hasLocation(#20600,#20601)
|
||||
#20602=*
|
||||
regexpterm(#20602,8,#20596,2,"[^>]*")
|
||||
#20603=@"loc,{#10000},44,8,44,12"
|
||||
locations_default(#20603,#10000,44,8,44,12)
|
||||
hasLocation(#20602,#20603)
|
||||
is_greedy(#20602)
|
||||
#20604=*
|
||||
regexpterm(#20604,23,#20602,0,"[^>]")
|
||||
#20605=@"loc,{#10000},44,8,44,11"
|
||||
locations_default(#20605,#10000,44,8,44,11)
|
||||
hasLocation(#20604,#20605)
|
||||
is_inverted(#20604)
|
||||
#20606=*
|
||||
regexpterm(#20606,14,#20604,0,">")
|
||||
#20607=@"loc,{#10000},44,10,44,10"
|
||||
locations_default(#20607,#10000,44,10,44,10)
|
||||
hasLocation(#20606,#20607)
|
||||
regexp_const_value(#20606,">")
|
||||
#20608=*
|
||||
regexpterm(#20608,14,#20596,3,">")
|
||||
#20609=@"loc,{#10000},44,13,44,13"
|
||||
locations_default(#20609,#10000,44,13,44,13)
|
||||
hasLocation(#20608,#20609)
|
||||
regexp_const_value(#20608,">")
|
||||
#20610=*
|
||||
regexpterm(#20610,13,#20596,4,"((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)")
|
||||
#20611=@"loc,{#10000},44,14,44,51"
|
||||
locations_default(#20611,#10000,44,14,44,51)
|
||||
hasLocation(#20610,#20611)
|
||||
is_capture(#20610,1)
|
||||
#20612=*
|
||||
regexpterm(#20612,8,#20610,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?")
|
||||
#20613=@"loc,{#10000},44,15,44,50"
|
||||
locations_default(#20613,#10000,44,15,44,50)
|
||||
hasLocation(#20612,#20613)
|
||||
#20614=*
|
||||
regexpterm(#20614,13,#20612,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))")
|
||||
#20615=@"loc,{#10000},44,15,44,48"
|
||||
locations_default(#20615,#10000,44,15,44,48)
|
||||
hasLocation(#20614,#20615)
|
||||
#20616=*
|
||||
regexpterm(#20616,0,#20614,0,"(?=([^<]+))\2|<(?!tpl\b[^>]*>)")
|
||||
#20617=@"loc,{#10000},44,18,44,47"
|
||||
locations_default(#20617,#10000,44,18,44,47)
|
||||
hasLocation(#20616,#20617)
|
||||
#20618=*
|
||||
regexpterm(#20618,1,#20616,0,"(?=([^<]+))\2")
|
||||
#20619=@"loc,{#10000},44,18,44,30"
|
||||
locations_default(#20619,#10000,44,18,44,30)
|
||||
hasLocation(#20618,#20619)
|
||||
#20620=*
|
||||
regexpterm(#20620,6,#20618,0,"(?=([^<]+))")
|
||||
#20621=@"loc,{#10000},44,18,44,28"
|
||||
locations_default(#20621,#10000,44,18,44,28)
|
||||
hasLocation(#20620,#20621)
|
||||
#20622=*
|
||||
regexpterm(#20622,13,#20620,0,"([^<]+)")
|
||||
#20623=@"loc,{#10000},44,21,44,27"
|
||||
locations_default(#20623,#10000,44,21,44,27)
|
||||
hasLocation(#20622,#20623)
|
||||
is_capture(#20622,2)
|
||||
#20624=*
|
||||
regexpterm(#20624,9,#20622,0,"[^<]+")
|
||||
#20625=@"loc,{#10000},44,22,44,26"
|
||||
locations_default(#20625,#10000,44,22,44,26)
|
||||
hasLocation(#20624,#20625)
|
||||
is_greedy(#20624)
|
||||
#20626=*
|
||||
regexpterm(#20626,23,#20624,0,"[^<]")
|
||||
#20627=@"loc,{#10000},44,22,44,25"
|
||||
locations_default(#20627,#10000,44,22,44,25)
|
||||
hasLocation(#20626,#20627)
|
||||
is_inverted(#20626)
|
||||
#20628=*
|
||||
regexpterm(#20628,14,#20626,0,"<")
|
||||
#20629=@"loc,{#10000},44,24,44,24"
|
||||
locations_default(#20629,#10000,44,24,44,24)
|
||||
hasLocation(#20628,#20629)
|
||||
regexp_const_value(#20628,"<")
|
||||
#20630=*
|
||||
regexpterm(#20630,22,#20618,1,"\2")
|
||||
#20631=@"loc,{#10000},44,29,44,30"
|
||||
locations_default(#20631,#10000,44,29,44,30)
|
||||
hasLocation(#20630,#20631)
|
||||
backref(#20630,2)
|
||||
#20632=*
|
||||
regexpterm(#20632,1,#20616,1,"<(?!tpl\b[^>]*>)")
|
||||
#20633=@"loc,{#10000},44,32,44,47"
|
||||
locations_default(#20633,#10000,44,32,44,47)
|
||||
hasLocation(#20632,#20633)
|
||||
#20634=*
|
||||
regexpterm(#20634,14,#20632,0,"<")
|
||||
#20635=@"loc,{#10000},44,32,44,32"
|
||||
locations_default(#20635,#10000,44,32,44,32)
|
||||
hasLocation(#20634,#20635)
|
||||
regexp_const_value(#20634,"<")
|
||||
#20636=*
|
||||
regexpterm(#20636,7,#20632,1,"(?!tpl\b[^>]*>)")
|
||||
#20637=@"loc,{#10000},44,33,44,47"
|
||||
locations_default(#20637,#10000,44,33,44,47)
|
||||
hasLocation(#20636,#20637)
|
||||
#20638=*
|
||||
regexpterm(#20638,1,#20636,0,"tpl\b[^>]*>")
|
||||
#20639=@"loc,{#10000},44,36,44,46"
|
||||
locations_default(#20639,#10000,44,36,44,46)
|
||||
hasLocation(#20638,#20639)
|
||||
#20640=*
|
||||
regexpterm(#20640,14,#20638,0,"tpl")
|
||||
#20641=@"loc,{#10000},44,36,44,38"
|
||||
locations_default(#20641,#10000,44,36,44,38)
|
||||
hasLocation(#20640,#20641)
|
||||
regexp_const_value(#20640,"tpl")
|
||||
#20642=*
|
||||
regexpterm(#20642,4,#20638,1,"\b")
|
||||
#20643=@"loc,{#10000},44,39,44,40"
|
||||
locations_default(#20643,#10000,44,39,44,40)
|
||||
hasLocation(#20642,#20643)
|
||||
#20644=*
|
||||
regexpterm(#20644,8,#20638,2,"[^>]*")
|
||||
#20645=@"loc,{#10000},44,41,44,45"
|
||||
locations_default(#20645,#10000,44,41,44,45)
|
||||
hasLocation(#20644,#20645)
|
||||
is_greedy(#20644)
|
||||
#20646=*
|
||||
regexpterm(#20646,23,#20644,0,"[^>]")
|
||||
#20647=@"loc,{#10000},44,41,44,44"
|
||||
locations_default(#20647,#10000,44,41,44,44)
|
||||
hasLocation(#20646,#20647)
|
||||
is_inverted(#20646)
|
||||
#20648=*
|
||||
regexpterm(#20648,14,#20646,0,">")
|
||||
#20649=@"loc,{#10000},44,43,44,43"
|
||||
locations_default(#20649,#10000,44,43,44,43)
|
||||
hasLocation(#20648,#20649)
|
||||
regexp_const_value(#20648,">")
|
||||
#20650=*
|
||||
regexpterm(#20650,14,#20638,3,">")
|
||||
#20651=@"loc,{#10000},44,46,44,46"
|
||||
locations_default(#20651,#10000,44,46,44,46)
|
||||
hasLocation(#20650,#20651)
|
||||
regexp_const_value(#20650,">")
|
||||
#20652=*
|
||||
regexpterm(#20652,14,#20596,5,"<")
|
||||
#20653=@"loc,{#10000},44,52,44,52"
|
||||
locations_default(#20653,#10000,44,52,44,52)
|
||||
hasLocation(#20652,#20653)
|
||||
regexp_const_value(#20652,"<")
|
||||
#20654=*
|
||||
regexpterm(#20654,21,#20596,6,"\/")
|
||||
#20655=@"loc,{#10000},44,53,44,54"
|
||||
locations_default(#20655,#10000,44,53,44,54)
|
||||
hasLocation(#20654,#20655)
|
||||
regexp_const_value(#20654,"/")
|
||||
#20656=*
|
||||
regexpterm(#20656,14,#20596,7,"tpl>")
|
||||
#20657=@"loc,{#10000},44,55,44,58"
|
||||
locations_default(#20657,#10000,44,55,44,58)
|
||||
hasLocation(#20656,#20657)
|
||||
regexp_const_value(#20656,"tpl>")
|
||||
#20658=*
|
||||
entry_cfg_node(#20658,#20001)
|
||||
#20659=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20659,#10000,1,1,1,0)
|
||||
hasLocation(#20658,#20659)
|
||||
#20660=*
|
||||
exit_cfg_node(#20660,#20001)
|
||||
hasLocation(#20660,#20267)
|
||||
successor(#20594,#20595)
|
||||
successor(#20595,#20660)
|
||||
successor(#20590,#20591)
|
||||
successor(#20591,#20594)
|
||||
successor(#20586,#20587)
|
||||
successor(#20587,#20590)
|
||||
successor(#20580,#20581)
|
||||
successor(#20581,#20586)
|
||||
successor(#20574,#20575)
|
||||
successor(#20575,#20580)
|
||||
successor(#20566,#20567)
|
||||
successor(#20567,#20574)
|
||||
successor(#20550,#20551)
|
||||
#20595=*
|
||||
regexpterm(#20595,14,#20593,0,"<tpl")
|
||||
#20596=@"loc,{#10000},44,2,44,5"
|
||||
locations_default(#20596,#10000,44,2,44,5)
|
||||
hasLocation(#20595,#20596)
|
||||
regexp_const_value(#20595,"<tpl")
|
||||
#20597=*
|
||||
regexpterm(#20597,4,#20593,1,"\b")
|
||||
#20598=@"loc,{#10000},44,6,44,7"
|
||||
locations_default(#20598,#10000,44,6,44,7)
|
||||
hasLocation(#20597,#20598)
|
||||
#20599=*
|
||||
regexpterm(#20599,8,#20593,2,"[^>]*")
|
||||
#20600=@"loc,{#10000},44,8,44,12"
|
||||
locations_default(#20600,#10000,44,8,44,12)
|
||||
hasLocation(#20599,#20600)
|
||||
is_greedy(#20599)
|
||||
#20601=*
|
||||
regexpterm(#20601,23,#20599,0,"[^>]")
|
||||
#20602=@"loc,{#10000},44,8,44,11"
|
||||
locations_default(#20602,#10000,44,8,44,11)
|
||||
hasLocation(#20601,#20602)
|
||||
is_inverted(#20601)
|
||||
#20603=*
|
||||
regexpterm(#20603,14,#20601,0,">")
|
||||
#20604=@"loc,{#10000},44,10,44,10"
|
||||
locations_default(#20604,#10000,44,10,44,10)
|
||||
hasLocation(#20603,#20604)
|
||||
regexp_const_value(#20603,">")
|
||||
#20605=*
|
||||
regexpterm(#20605,14,#20593,3,">")
|
||||
#20606=@"loc,{#10000},44,13,44,13"
|
||||
locations_default(#20606,#10000,44,13,44,13)
|
||||
hasLocation(#20605,#20606)
|
||||
regexp_const_value(#20605,">")
|
||||
#20607=*
|
||||
regexpterm(#20607,13,#20593,4,"((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)")
|
||||
#20608=@"loc,{#10000},44,14,44,51"
|
||||
locations_default(#20608,#10000,44,14,44,51)
|
||||
hasLocation(#20607,#20608)
|
||||
is_capture(#20607,1)
|
||||
#20609=*
|
||||
regexpterm(#20609,8,#20607,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?")
|
||||
#20610=@"loc,{#10000},44,15,44,50"
|
||||
locations_default(#20610,#10000,44,15,44,50)
|
||||
hasLocation(#20609,#20610)
|
||||
#20611=*
|
||||
regexpterm(#20611,13,#20609,0,"(?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))")
|
||||
#20612=@"loc,{#10000},44,15,44,48"
|
||||
locations_default(#20612,#10000,44,15,44,48)
|
||||
hasLocation(#20611,#20612)
|
||||
#20613=*
|
||||
regexpterm(#20613,0,#20611,0,"(?=([^<]+))\2|<(?!tpl\b[^>]*>)")
|
||||
#20614=@"loc,{#10000},44,18,44,47"
|
||||
locations_default(#20614,#10000,44,18,44,47)
|
||||
hasLocation(#20613,#20614)
|
||||
#20615=*
|
||||
regexpterm(#20615,1,#20613,0,"(?=([^<]+))\2")
|
||||
#20616=@"loc,{#10000},44,18,44,30"
|
||||
locations_default(#20616,#10000,44,18,44,30)
|
||||
hasLocation(#20615,#20616)
|
||||
#20617=*
|
||||
regexpterm(#20617,6,#20615,0,"(?=([^<]+))")
|
||||
#20618=@"loc,{#10000},44,18,44,28"
|
||||
locations_default(#20618,#10000,44,18,44,28)
|
||||
hasLocation(#20617,#20618)
|
||||
#20619=*
|
||||
regexpterm(#20619,13,#20617,0,"([^<]+)")
|
||||
#20620=@"loc,{#10000},44,21,44,27"
|
||||
locations_default(#20620,#10000,44,21,44,27)
|
||||
hasLocation(#20619,#20620)
|
||||
is_capture(#20619,2)
|
||||
#20621=*
|
||||
regexpterm(#20621,9,#20619,0,"[^<]+")
|
||||
#20622=@"loc,{#10000},44,22,44,26"
|
||||
locations_default(#20622,#10000,44,22,44,26)
|
||||
hasLocation(#20621,#20622)
|
||||
is_greedy(#20621)
|
||||
#20623=*
|
||||
regexpterm(#20623,23,#20621,0,"[^<]")
|
||||
#20624=@"loc,{#10000},44,22,44,25"
|
||||
locations_default(#20624,#10000,44,22,44,25)
|
||||
hasLocation(#20623,#20624)
|
||||
is_inverted(#20623)
|
||||
#20625=*
|
||||
regexpterm(#20625,14,#20623,0,"<")
|
||||
#20626=@"loc,{#10000},44,24,44,24"
|
||||
locations_default(#20626,#10000,44,24,44,24)
|
||||
hasLocation(#20625,#20626)
|
||||
regexp_const_value(#20625,"<")
|
||||
#20627=*
|
||||
regexpterm(#20627,22,#20615,1,"\2")
|
||||
#20628=@"loc,{#10000},44,29,44,30"
|
||||
locations_default(#20628,#10000,44,29,44,30)
|
||||
hasLocation(#20627,#20628)
|
||||
backref(#20627,2)
|
||||
#20629=*
|
||||
regexpterm(#20629,1,#20613,1,"<(?!tpl\b[^>]*>)")
|
||||
#20630=@"loc,{#10000},44,32,44,47"
|
||||
locations_default(#20630,#10000,44,32,44,47)
|
||||
hasLocation(#20629,#20630)
|
||||
#20631=*
|
||||
regexpterm(#20631,14,#20629,0,"<")
|
||||
#20632=@"loc,{#10000},44,32,44,32"
|
||||
locations_default(#20632,#10000,44,32,44,32)
|
||||
hasLocation(#20631,#20632)
|
||||
regexp_const_value(#20631,"<")
|
||||
#20633=*
|
||||
regexpterm(#20633,7,#20629,1,"(?!tpl\b[^>]*>)")
|
||||
#20634=@"loc,{#10000},44,33,44,47"
|
||||
locations_default(#20634,#10000,44,33,44,47)
|
||||
hasLocation(#20633,#20634)
|
||||
#20635=*
|
||||
regexpterm(#20635,1,#20633,0,"tpl\b[^>]*>")
|
||||
#20636=@"loc,{#10000},44,36,44,46"
|
||||
locations_default(#20636,#10000,44,36,44,46)
|
||||
hasLocation(#20635,#20636)
|
||||
#20637=*
|
||||
regexpterm(#20637,14,#20635,0,"tpl")
|
||||
#20638=@"loc,{#10000},44,36,44,38"
|
||||
locations_default(#20638,#10000,44,36,44,38)
|
||||
hasLocation(#20637,#20638)
|
||||
regexp_const_value(#20637,"tpl")
|
||||
#20639=*
|
||||
regexpterm(#20639,4,#20635,1,"\b")
|
||||
#20640=@"loc,{#10000},44,39,44,40"
|
||||
locations_default(#20640,#10000,44,39,44,40)
|
||||
hasLocation(#20639,#20640)
|
||||
#20641=*
|
||||
regexpterm(#20641,8,#20635,2,"[^>]*")
|
||||
#20642=@"loc,{#10000},44,41,44,45"
|
||||
locations_default(#20642,#10000,44,41,44,45)
|
||||
hasLocation(#20641,#20642)
|
||||
is_greedy(#20641)
|
||||
#20643=*
|
||||
regexpterm(#20643,23,#20641,0,"[^>]")
|
||||
#20644=@"loc,{#10000},44,41,44,44"
|
||||
locations_default(#20644,#10000,44,41,44,44)
|
||||
hasLocation(#20643,#20644)
|
||||
is_inverted(#20643)
|
||||
#20645=*
|
||||
regexpterm(#20645,14,#20643,0,">")
|
||||
#20646=@"loc,{#10000},44,43,44,43"
|
||||
locations_default(#20646,#10000,44,43,44,43)
|
||||
hasLocation(#20645,#20646)
|
||||
regexp_const_value(#20645,">")
|
||||
#20647=*
|
||||
regexpterm(#20647,14,#20635,3,">")
|
||||
#20648=@"loc,{#10000},44,46,44,46"
|
||||
locations_default(#20648,#10000,44,46,44,46)
|
||||
hasLocation(#20647,#20648)
|
||||
regexp_const_value(#20647,">")
|
||||
#20649=*
|
||||
regexpterm(#20649,14,#20593,5,"<")
|
||||
#20650=@"loc,{#10000},44,52,44,52"
|
||||
locations_default(#20650,#10000,44,52,44,52)
|
||||
hasLocation(#20649,#20650)
|
||||
regexp_const_value(#20649,"<")
|
||||
#20651=*
|
||||
regexpterm(#20651,21,#20593,6,"\/")
|
||||
#20652=@"loc,{#10000},44,53,44,54"
|
||||
locations_default(#20652,#10000,44,53,44,54)
|
||||
hasLocation(#20651,#20652)
|
||||
regexp_const_value(#20651,"/")
|
||||
#20653=*
|
||||
regexpterm(#20653,14,#20593,7,"tpl>")
|
||||
#20654=@"loc,{#10000},44,55,44,58"
|
||||
locations_default(#20654,#10000,44,55,44,58)
|
||||
hasLocation(#20653,#20654)
|
||||
regexp_const_value(#20653,"tpl>")
|
||||
#20655=*
|
||||
entry_cfg_node(#20655,#20001)
|
||||
#20656=@"loc,{#10000},1,1,1,0"
|
||||
locations_default(#20656,#10000,1,1,1,0)
|
||||
hasLocation(#20655,#20656)
|
||||
#20657=*
|
||||
exit_cfg_node(#20657,#20001)
|
||||
hasLocation(#20657,#20267)
|
||||
successor(#20591,#20592)
|
||||
successor(#20592,#20657)
|
||||
successor(#20587,#20588)
|
||||
successor(#20588,#20591)
|
||||
successor(#20583,#20584)
|
||||
successor(#20584,#20587)
|
||||
successor(#20577,#20578)
|
||||
successor(#20578,#20583)
|
||||
successor(#20571,#20572)
|
||||
successor(#20572,#20577)
|
||||
successor(#20564,#20565)
|
||||
successor(#20565,#20571)
|
||||
successor(#20549,#20550)
|
||||
successor(#20550,#20564)
|
||||
successor(#20540,#20541)
|
||||
successor(#20540,#20541)
|
||||
successor(#20541,#20549)
|
||||
successor(#20530,#20531)
|
||||
successor(#20531,#20540)
|
||||
@@ -2125,6 +2113,6 @@ successor(#20273,#20274)
|
||||
successor(#20273,#20274)
|
||||
successor(#20274,#20281)
|
||||
successor(#20269,#20270)
|
||||
successor(#20270,#20273)
|
||||
successor(#20270,#20273)
|
||||
successor(#20655,#20269)
|
||||
numlines(#10000,44,44,0)
|
||||
|
||||
@@ -168,3 +168,7 @@
|
||||
| tst.js:351:15:351:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
|
||||
| tst.js:352:15:352:16 | a* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
|
||||
| tst.js:353:15:353:16 | a+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
|
||||
| tst.js:360:15:360:30 | ((?:a{\|-)\|\\w\\{)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{'. |
|
||||
| tst.js:361:15:361:33 | ((?:a{0\|-)\|\\w\\{\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0'. |
|
||||
| tst.js:362:15:362:35 | ((?:a{0,\|-)\|\\w\\{\\d,)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,'. |
|
||||
| tst.js:363:15:363:38 | ((?:a{0,2\|-)\|\\w\\{\\d,\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,2'. |
|
||||
|
||||
@@ -355,3 +355,12 @@ var bad82 = /(a+)+b/;
|
||||
// GOOD
|
||||
var good40 = /(a|b)+/;
|
||||
var good41 = /(?:[\s;,"'<>(){}|[\]@=+*]|:(?![/\\]))+/;
|
||||
|
||||
// NOT GOOD
|
||||
var bad83 = /^((?:a{|-)|\w\{)+X$/;
|
||||
var bad84 = /^((?:a{0|-)|\w\{\d)+X$/;
|
||||
var bad85 = /^((?:a{0,|-)|\w\{\d,)+X$/;
|
||||
var bad86 = /^((?:a{0,2|-)|\w\{\d,\d)+X$/;
|
||||
|
||||
// GOOD:
|
||||
var good42 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/;
|
||||
@@ -1,3 +1,2 @@
|
||||
| tst.js:1:4:1:4 | expected '}' | Malformed regular expression: expected '}'. |
|
||||
| tst.js:4:29:4:29 | unexpected character | Malformed regular expression: unexpected character. |
|
||||
| tst.js:4:43:4:43 | unexpected character | Malformed regular expression: unexpected character. |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/a{1/;
|
||||
/a{1/; // OK
|
||||
|
||||
function f() {
|
||||
return a.replace(/<\!--(?!{cke_protected})[\s\S]+?--\>/g, "foo");
|
||||
|
||||
@@ -85,3 +85,8 @@ function nonWordBoundary(x) {
|
||||
function emptyRegex(x) {
|
||||
return new RegExp("").test(x); // NOT OK
|
||||
}
|
||||
|
||||
function parserTest(x) {
|
||||
/(\w\s*:\s*[^:}]+|#){|@import[^\n]+(?:url|,)/.test(x); // OK
|
||||
/^((?:a{0,2}|-)|\w\{\d,\d\})+X$/.text(x); // ok
|
||||
}
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -207,18 +207,6 @@ private predicate fullBarrier(Node node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepSource extends Node {
|
||||
AdditionalFlowStepSource() { any(Configuration c).isAdditionalFlowStep(this, _) }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate isAdditionalFlowStep(
|
||||
AdditionalFlowStepSource node1, Node node2, DataFlowCallable callable1, Configuration config
|
||||
) {
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
callable1 = node1.getEnclosingCallable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -237,7 +225,8 @@ private predicate localFlowStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` does not jump between callables.
|
||||
*/
|
||||
private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration config) {
|
||||
isAdditionalFlowStep(node1, node2, node2.getEnclosingCallable(), config) and
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) = getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
@@ -259,14 +248,12 @@ private predicate jumpStep(Node node1, Node node2, Configuration config) {
|
||||
* Holds if the additional step from `node1` to `node2` jumps between callables.
|
||||
*/
|
||||
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
|
||||
exists(DataFlowCallable callable1 |
|
||||
isAdditionalFlowStep(node1, node2, callable1, config) and
|
||||
node2.getEnclosingCallable() != callable1 and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
config.isAdditionalFlowStep(node1, node2) and
|
||||
getNodeEnclosingCallable(node1) != getNodeEnclosingCallable(node2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +588,7 @@ private module Stage1 {
|
||||
) {
|
||||
exists(ReturnNodeExt ret |
|
||||
throughFlowNodeCand(ret, config) and
|
||||
callable = ret.getEnclosingCallable() and
|
||||
callable = getNodeEnclosingCallable(ret) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
@@ -614,7 +601,7 @@ private module Stage1 {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
returnFlowCallableNodeCand(c, kind, config) and
|
||||
p.getEnclosingCallable() = c and
|
||||
getNodeEnclosingCallable(p) = c and
|
||||
exists(ap) and
|
||||
// we don't expect a parameter to return stored in itself
|
||||
not exists(int pos |
|
||||
@@ -778,7 +765,7 @@ private module Stage2 {
|
||||
bindingset[result, ap]
|
||||
private ApApprox getApprox(Ap ap) { any() }
|
||||
|
||||
private ApNil getApNil(Node node) { any() }
|
||||
private ApNil getApNil(Node node) { PrevStage::revFlow(node, _) and exists(result) }
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
|
||||
@@ -966,7 +953,7 @@ private module Stage2 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -985,7 +972,7 @@ private module Stage2 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1216,13 +1203,13 @@ private module Stage2 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -1348,7 +1335,7 @@ private module LocalFlowBigStep {
|
||||
t = getNodeType(node2)
|
||||
) and
|
||||
node1 != node2 and
|
||||
cc.relevantFor(node1.getEnclosingCallable()) and
|
||||
cc.relevantFor(getNodeEnclosingCallable(node1)) and
|
||||
not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
|
||||
Stage2::revFlow(node2, unbind(config))
|
||||
or
|
||||
@@ -1397,7 +1384,9 @@ private module Stage3 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TFrontNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
|
||||
@@ -1594,7 +1583,7 @@ private module Stage3 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -1613,7 +1602,7 @@ private module Stage3 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -1844,13 +1833,13 @@ private module Stage3 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2090,7 +2079,9 @@ private module Stage4 {
|
||||
|
||||
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
|
||||
|
||||
private ApNil getApNil(Node node) { result = TNil(getNodeType(node)) }
|
||||
private ApNil getApNil(Node node) {
|
||||
PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
|
||||
}
|
||||
|
||||
bindingset[tc, tail]
|
||||
private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
|
||||
@@ -2135,7 +2126,7 @@ private module Stage4 {
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(Node node, Cc cc, Configuration config) {
|
||||
localFlowEntry(node, config) and
|
||||
result = getLocalCallContext(cc, node.getEnclosingCallable())
|
||||
result = getLocalCallContext(cc, getNodeEnclosingCallable(node))
|
||||
}
|
||||
|
||||
private predicate localStep(
|
||||
@@ -2300,7 +2291,7 @@ private module Stage4 {
|
||||
exists(ArgumentNode arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
)
|
||||
@@ -2319,7 +2310,7 @@ private module Stage4 {
|
||||
exists(ReturnNodeExt ret, boolean allowsFieldFlow, DataFlowCallable inner |
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
inner = getNodeEnclosingCallable(ret) and
|
||||
checkCallContextReturn(innercc, inner, call) and
|
||||
ccOut = getCallContextReturn(inner, call)
|
||||
|
|
||||
@@ -2550,13 +2541,13 @@ private module Stage4 {
|
||||
ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
|
||||
) {
|
||||
revFlow(p, true, apSome(ap0), ap, config) and
|
||||
c = p.getEnclosingCallable()
|
||||
c = getNodeEnclosingCallable(p)
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
c = getNodeEnclosingCallable(ret) and
|
||||
revFlow(ret, true, apSome(_), ap0, config) and
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
|
||||
kind = ret.getKind() and
|
||||
@@ -2590,7 +2581,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
|
||||
Stage4::parameterMayFlowThrough(_, c, apa, _) and
|
||||
Stage4::revFlow(n, true, _, apa0, config) and
|
||||
Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
|
||||
n.getEnclosingCallable() = c
|
||||
getNodeEnclosingCallable(n) = c
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3119,7 +3110,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
|
||||
conf = mid.getConfiguration() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
localCC = getLocalCallContext(cc, midnode.getEnclosingCallable()) and
|
||||
localCC = getLocalCallContext(cc, getNodeEnclosingCallable(midnode)) and
|
||||
ap0 = mid.getAp()
|
||||
|
|
||||
localFlowBigStep(midnode, node, true, _, conf, localCC) and
|
||||
@@ -3405,14 +3396,14 @@ private module FlowExploration {
|
||||
// flow out of a callable
|
||||
viableReturnPosOut(_, getReturnPosition(node1), node2)
|
||||
|
|
||||
c1 = node1.getEnclosingCallable() and
|
||||
c2 = node2.getEnclosingCallable() and
|
||||
c1 = getNodeEnclosingCallable(node1) and
|
||||
c2 = getNodeEnclosingCallable(node2) and
|
||||
c1 != c2
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSource(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
|
||||
@@ -3420,7 +3411,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
|
||||
exists(Node n | config.isSink(n) and c = n.getEnclosingCallable())
|
||||
exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
|
||||
or
|
||||
exists(DataFlowCallable mid |
|
||||
interestingCallableSink(mid, config) and callableStep(c, mid, config)
|
||||
@@ -3449,13 +3440,13 @@ private module FlowExploration {
|
||||
exists(Node n, Configuration config |
|
||||
ce1 = TCallableSrc() and
|
||||
config.isSource(n) and
|
||||
ce2 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce2 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
or
|
||||
exists(Node n, Configuration config |
|
||||
ce2 = TCallableSink() and
|
||||
config.isSink(n) and
|
||||
ce1 = TCallable(n.getEnclosingCallable(), config)
|
||||
ce1 = TCallable(getNodeEnclosingCallable(n), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3586,7 +3577,7 @@ private module FlowExploration {
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
|
||||
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSrc(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
} or
|
||||
TPartialPathNodeRev(
|
||||
Node node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
|
||||
@@ -3603,7 +3594,7 @@ private module FlowExploration {
|
||||
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
|
||||
not clearsContent(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3662,7 +3653,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSourceDistance() {
|
||||
result = distSrc(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSrc(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,7 +3661,7 @@ private module FlowExploration {
|
||||
* of interprocedural steps.
|
||||
*/
|
||||
int getSinkDistance() {
|
||||
result = distSink(this.getNode().getEnclosingCallable(), this.getConfiguration())
|
||||
result = distSink(getNodeEnclosingCallable(this.getNode()), this.getConfiguration())
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
|
||||
@@ -447,7 +447,7 @@ private module Cached {
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
exists(Node n | n.getEnclosingCallable() = callable | isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -592,7 +592,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
|
||||
override string toString() { result = "CcSomeCall" }
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
exists(ParameterNode p | p.getEnclosingCallable() = callable)
|
||||
exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { any() }
|
||||
@@ -637,7 +637,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
|
||||
}
|
||||
|
||||
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | n.getEnclosingCallable() = callable and isUnreachableInCall(n, call))
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,9 +746,22 @@ class ReturnPosition extends TReturnPosition0 {
|
||||
string toString() { result = "[" + kind + "] " + c }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
|
||||
* predicate ensures that joins go from `n` to the result instead of the other
|
||||
* way around.
|
||||
*/
|
||||
pragma[inline]
|
||||
DataFlowCallable getNodeEnclosingCallable(Node n) {
|
||||
exists(Node n0 |
|
||||
pragma[only_bind_into](n0) = n and
|
||||
pragma[only_bind_into](result) = n0.getEnclosingCallable()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) {
|
||||
result = ret.getEnclosingCallable()
|
||||
result = getNodeEnclosingCallable(ret)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
Reference in New Issue
Block a user