Merge branch 'main' of github.com:github/codeql into python-port-insecure-protocol

This commit is contained in:
Rasmus Lerchedahl Petersen
2021-03-15 17:37:28 +01:00
1301 changed files with 31762 additions and 8801 deletions

View File

@@ -2,7 +2,7 @@
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="CommentedOutCodeQuery.qhelp" />
<include src="CommentedOutCodeExample.qhelp" />
<include src="CommentedOutCodeReferences.qhelp" />
<include src="CommentedOutCodeQuery.inc.qhelp" />
<include src="CommentedOutCodeExample.inc.qhelp" />
<include src="CommentedOutCodeReferences.inc.qhelp" />
</qhelp>

View File

@@ -2,7 +2,7 @@
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="CommentedOutCodeMetricOverview.qhelp" />
<include src="CommentedOutCodeExample.qhelp" />
<include src="CommentedOutCodeReferences.qhelp" />
<include src="CommentedOutCodeMetricOverview.inc.qhelp" />
<include src="CommentedOutCodeExample.inc.qhelp" />
<include src="CommentedOutCodeReferences.inc.qhelp" />
</qhelp>

View File

@@ -2,5 +2,5 @@
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<include src="FLinesOfDuplicatedCodeCommon.qhelp" />
<include src="FLinesOfDuplicatedCodeCommon.inc.qhelp" />
</qhelp>

View File

@@ -14,7 +14,7 @@ for a number of reasons.
</p>
</overview>
<include src="DuplicationProblems.qhelp" />
<include src="DuplicationProblems.inc.qhelp" />
<recommendation>

View File

@@ -10,7 +10,7 @@ duplicated code.
</p>
</overview>
<include src="DuplicationProblems.qhelp" />
<include src="DuplicationProblems.inc.qhelp" />
<recommendation>

View File

@@ -11,28 +11,86 @@
*/
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
Value aSocket() { result.getClass() = Value::named("socket.socket") }
CallNode socketBindCall() {
result = aSocket().attr("bind").(CallableValue).getACall() and major_version() = 3
or
result.getFunction().(AttrNode).getObject("bind").pointsTo(aSocket()) and
major_version() = 2
/** Gets a hostname that can be used to bind to all interfaces. */
private string vulnerableHostname() {
result in [
// IPv4
"0.0.0.0", "",
// IPv6
"::", "::0"
]
}
string allInterfaces() { result = "0.0.0.0" or result = "" }
Value getTextValue(string address) {
result = Value::forUnicode(address) and major_version() = 3
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
private DataFlow::LocalSourceNode vulnerableHostnameRef(DataFlow::TypeTracker t, string hostname) {
t.start() and
exists(StrConst allInterfacesStrConst | hostname = vulnerableHostname() |
allInterfacesStrConst.getText() = hostname and
result.asExpr() = allInterfacesStrConst
)
or
result = Value::forString(address) and major_version() = 2
// Due to bad performance when using normal setup with `vulnerableHostnameRef(t2, hostname).track(t2, t)`
// we have inlined that code and forced a join
exists(DataFlow::TypeTracker t2 |
exists(DataFlow::StepSummary summary |
vulnerableHostnameRef_first_join(t2, hostname, result, summary) and
t = t2.append(summary)
)
)
}
from CallNode call, TupleValue args, string address
pragma[nomagic]
private predicate vulnerableHostnameRef_first_join(
DataFlow::TypeTracker t2, string hostname, DataFlow::Node res, DataFlow::StepSummary summary
) {
DataFlow::StepSummary::step(vulnerableHostnameRef(t2, hostname), res, summary)
}
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
DataFlow::Node vulnerableHostnameRef(string hostname) {
vulnerableHostnameRef(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
}
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
private DataFlow::LocalSourceNode vulnerableAddressTuple(DataFlow::TypeTracker t, string hostname) {
t.start() and
result.asExpr() = any(Tuple tup | tup.getElt(0) = vulnerableHostnameRef(hostname).asExpr())
or
// Due to bad performance when using normal setup with `vulnerableAddressTuple(t2, hostname).track(t2, t)`
// we have inlined that code and forced a join
exists(DataFlow::TypeTracker t2 |
exists(DataFlow::StepSummary summary |
vulnerableAddressTuple_first_join(t2, hostname, result, summary) and
t = t2.append(summary)
)
)
}
pragma[nomagic]
private predicate vulnerableAddressTuple_first_join(
DataFlow::TypeTracker t2, string hostname, DataFlow::Node res, DataFlow::StepSummary summary
) {
DataFlow::StepSummary::step(vulnerableAddressTuple(t2, hostname), res, summary)
}
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
DataFlow::Node vulnerableAddressTuple(string hostname) {
vulnerableAddressTuple(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
}
/**
* Gets an instance of `socket.socket` using _some_ address family.
*
* See https://docs.python.org/3/library/socket.html
*/
API::Node socketInstance() { result = API::moduleImport("socket").getMember("socket").getReturn() }
from DataFlow::CallCfgNode bindCall, DataFlow::Node addressArg, string hostname
where
call = socketBindCall() and
call.getArg(0).pointsTo(args) and
args.getItem(0) = getTextValue(address) and
address = allInterfaces()
select call.getNode(), "'" + address + "' binds a socket to all interfaces."
bindCall = socketInstance().getMember("bind").getACall() and
addressArg = bindCall.getArg(0) and
addressArg = vulnerableAddressTuple(hostname)
select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces."

View File

@@ -11,12 +11,25 @@
*/
import python
import semmle.python.web.flask.General
import semmle.python.dataflow.new.DataFlow
import semmle.python.ApiGraphs
import semmle.python.frameworks.Flask
from CallNode call, Value isTrue
/** Gets a reference to a truthy literal. */
private DataFlow::LocalSourceNode truthyLiteral(DataFlow::TypeTracker t) {
t.start() and
result.asExpr().(ImmutableLiteral).booleanValue() = true
or
exists(DataFlow::TypeTracker t2 | result = truthyLiteral(t2).track(t2, t))
}
/** Gets a reference to a truthy literal. */
DataFlow::Node truthyLiteral() { truthyLiteral(DataFlow::TypeTracker::end()).flowsTo(result) }
from DataFlow::CallCfgNode call, DataFlow::Node debugArg
where
call = theFlaskClass().declaredAttribute("run").(FunctionValue).getACall() and
call.getArgByName("debug").pointsTo(isTrue) and
isTrue.getDefiniteBooleanValue() = true
call.getFunction() = Flask::FlaskApp::instance().getMember("run").getAUse() and
debugArg in [call.getArg(2), call.getArgByName("debug")] and
debugArg = truthyLiteral()
select call,
"A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger."

View File

@@ -7,8 +7,8 @@
<p> A local variable is defined (by an assignment) but never used.
</p>
<include src="UnusedVariableNaming.qhelp" />
<include src="UnusedTuple.qhelp" />
<include src="UnusedVariableNaming.inc.qhelp" />
<include src="UnusedTuple.inc.qhelp" />
</overview>
<recommendation>

View File

@@ -8,8 +8,8 @@
and is not explicitly made public by inclusion in the <code>__all__</code> list.
</p>
<include src="UnusedVariableNaming.qhelp" />
<include src="UnusedTuple.qhelp" />
<include src="UnusedVariableNaming.inc.qhelp" />
<include src="UnusedTuple.inc.qhelp" />
</overview>
<recommendation>

View File

@@ -9,7 +9,7 @@
<p> A parameter is never used.
</p>
<include src="UnusedVariableNaming.qhelp" />
<include src="UnusedVariableNaming.inc.qhelp" />
</overview>
<recommendation>

View File

@@ -0,0 +1,33 @@
/**
* @name Binding a socket to all network interfaces
* @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address
* and is therefore associated with security risks.
* @kind problem
*/
import python
Value aSocket() { result.getClass() = Value::named("socket.socket") }
CallNode socketBindCall() {
result = aSocket().attr("bind").(CallableValue).getACall() and major_version() = 3
or
result.getFunction().(AttrNode).getObject("bind").pointsTo(aSocket()) and
major_version() = 2
}
string allInterfaces() { result = "0.0.0.0" or result = "" }
Value getTextValue(string address) {
result = Value::forUnicode(address) and major_version() = 3
or
result = Value::forString(address) and major_version() = 2
}
from CallNode call, TupleValue args, string address
where
call = socketBindCall() and
call.getArg(0).pointsTo(args) and
args.getItem(0) = getTextValue(address) and
address = allInterfaces()
select call.getNode(), "'" + address + "' binds a socket to all interfaces."

View File

@@ -1,19 +1,7 @@
/**
* @name Uncontrolled data used in path expression
* @name OLD QUERY: Uncontrolled data used in path expression
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
* @id py/path-injection
* @tags correctness
* security
* external/owasp/owasp-a1
* external/cwe/cwe-022
* external/cwe/cwe-023
* external/cwe/cwe-036
* external/cwe/cwe-073
* external/cwe/cwe-099
*/
import python

View File

@@ -1,17 +1,8 @@
/**
* @name Uncontrolled command line
* @name OLD QUERY: Uncontrolled command line
* @description Using externally controlled strings in a command line may allow a malicious
* user to change the meaning of the command.
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
* @id py/command-line-injection
* @tags correctness
* security
* external/owasp/owasp-a1
* external/cwe/cwe-078
* external/cwe/cwe-088
*/
import python

View File

@@ -1,15 +1,8 @@
/**
* @name Reflected server-side cross-site scripting
* @name OLD QUERY: Reflected server-side cross-site scripting
* @description Writing user input directly to a web page
* allows for a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
* @id py/reflective-xss
* @tags security
* external/cwe/cwe-079
* external/cwe/cwe-116
*/
import python

View File

@@ -1,14 +1,8 @@
/**
* @name SQL query built from user-controlled sources
* @name OLD QUERY: SQL query built from user-controlled sources
* @description Building a SQL query from user-controlled sources is vulnerable to insertion of
* malicious SQL code by the user.
* @kind path-problem
* @problem.severity error
* @precision high
* @id py/sql-injection
* @tags security
* external/cwe/cwe-089
* external/owasp/owasp-a1
*/
import python

View File

@@ -3,15 +3,6 @@
* @description Interpreting unsanitized user input as code allows a malicious user arbitrary
* code execution.
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
* @id py/code-injection
* @tags security
* external/owasp/owasp-a1
* external/cwe/cwe-094
* external/cwe/cwe-095
* external/cwe/cwe-116
*/
import python

View File

@@ -1,14 +1,7 @@
/**
* @name Deserializing untrusted input
* @name OLD QUERY: Deserializing untrusted input
* @description Deserializing user-controlled data may allow attackers to execute arbitrary code.
* @kind path-problem
* @id py/unsafe-deserialization
* @problem.severity error
* @sub-severity high
* @precision high
* @tags external/cwe/cwe-502
* security
* serialization
*/
import python

View File

@@ -1,14 +1,8 @@
/**
* @name URL redirection from remote source
* @name OLD QUERY: URL redirection from remote source
* @description URL redirection based on unvalidated user input
* may cause redirection to malicious web sites.
* @kind path-problem
* @problem.severity error
* @sub-severity low
* @id py/url-redirection
* @tags security
* external/cwe/cwe-601
* @precision high
*/
import python

View File

@@ -1,10 +1,7 @@
/**
* Provides classes for modeling cryptographic libraries.
*/
/*
* The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll`
* which should be considered the definitive version (as of Feb 2018)
* Provides classes modeling cryptographic algorithms, separated into strong and weak variants.
*
* The classification into strong and weak are based on Wikipedia, OWASP and google (2017).
*/
/**
@@ -13,6 +10,8 @@
* The names are normalized: upper-case, no spaces, dashes or underscores.
*
* The names are inspired by the names used in real world crypto libraries.
*
* The classification into strong and weak are based on Wikipedia, OWASP and google (2017).
*/
private module AlgorithmNames {
predicate isStrongHashingAlgorithm(string name) {
@@ -81,14 +80,6 @@ private module AlgorithmNames {
}
predicate isWeakPasswordHashingAlgorithm(string name) { none() }
/**
* Normalizes `name`: upper-case, no spaces, dashes or underscores.
*
* All names of this module are in this normalized form.
*/
bindingset[name]
string normalizeName(string name) { result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") }
}
private import AlgorithmNames
@@ -121,10 +112,19 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
string toString() { result = getName() }
/**
* Gets the name of the algorithm.
* Gets the normalized name of this algorithm (upper-case, no spaces, dashes or underscores).
*/
abstract string getName();
/**
* Holds if the name of this algorithm matches `name` modulo case,
* white space, dashes, and underscores.
*/
bindingset[name]
predicate matchesName(string name) {
name.toUpperCase().regexpReplaceAll("[-_ ]", "") = getName()
}
/**
* Holds if this algorithm is weak.
*/

View File

@@ -216,6 +216,9 @@ module API {
*/
Node moduleImport(string m) { result = Impl::MkModuleImport(m) }
/** Gets a node corresponding to the built-in with the given name, if any. */
Node builtin(string n) { result = moduleImport("builtins").getMember(n) }
/**
* Provides the actual implementation of API graphs, cached for performance.
*
@@ -300,11 +303,18 @@ module API {
MkRoot() or
/** An abstract representative for imports of the module called `name`. */
MkModuleImport(string name) {
imports(_, name)
// Ignore the following module name for Python 2, as we alias `__builtin__` to `builtins` elsewhere
(name != "__builtin__" or major_version() = 3) and
(
imports(_, name)
or
// When we `import foo.bar.baz` we want to create API graph nodes also for the prefixes
// `foo` and `foo.bar`:
name = any(ImportExpr e | not e.isRelative()).getAnImportedModuleName()
)
or
// When we `import foo.bar.baz` we want to create API graph nodes also for the prefixes
// `foo` and `foo.bar`:
name = any(ImportExpr e | not e.isRelative()).getAnImportedModuleName()
// The `builtins` module should always be implicitly available
name = "builtins"
} or
/** A use of an API member at the node `nd`. */
MkUse(DataFlow::Node nd) { use(_, _, nd) }
@@ -339,6 +349,24 @@ module API {
)
}
private import semmle.python.types.Builtins as Builtins
/**
* Gets a data flow node that is likely to refer to a built-in with the name `name`.
*
* Currently this is an over-approximation, and does not account for things like overwriting a
* built-in with a different value.
*/
private DataFlow::Node likely_builtin(string name) {
result.asCfgNode() =
any(NameNode n |
n.isGlobal() and
n.isLoad() and
name = n.getId() and
name = any(Builtins::Builtin b).getName()
)
}
/**
* Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled
* `lbl` in the API graph.
@@ -369,6 +397,10 @@ module API {
ref.asExpr().(ClassExpr).getABase() = superclass.asExpr()
)
)
or
// Built-ins, treated as members of the module `builtins`
base = MkModuleImport("builtins") and
lbl = Label::member(any(string name | ref = likely_builtin(name)))
}
/**
@@ -381,6 +413,11 @@ module API {
imports(ref, name)
)
or
// Ensure the Python 2 `__builtin__` module gets the name of the Python 3 `builtins` module.
major_version() = 2 and
nd = MkModuleImport("builtins") and
imports(ref, "__builtin__")
or
nd = MkUse(ref)
}

View File

@@ -207,23 +207,14 @@ 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`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
simpleLocalFlowStep(node1, node2) and
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -234,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
@@ -256,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)
}
/**
@@ -598,7 +588,7 @@ private module Stage1 {
) {
exists(ReturnNodeExt ret |
throughFlowNodeCand(ret, config) and
callable = ret.getEnclosingCallable() and
callable = getNodeEnclosingCallable(ret) and
kind = ret.getKind()
)
}
@@ -611,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 |
@@ -775,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) }
@@ -963,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
)
@@ -982,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)
|
@@ -1213,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
@@ -1345,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
@@ -1394,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) }
@@ -1591,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
)
@@ -1610,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)
|
@@ -1841,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
@@ -2087,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) }
@@ -2132,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(
@@ -2297,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
)
@@ -2316,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)
|
@@ -2547,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
@@ -2587,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
)
}
@@ -3116,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
@@ -3402,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)
@@ -3417,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)
@@ -3446,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)
)
}
@@ -3583,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,
@@ -3600,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()
)
}
@@ -3659,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())
}
/**
@@ -3667,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() {

View File

@@ -207,23 +207,14 @@ 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`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
simpleLocalFlowStep(node1, node2) and
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -234,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
@@ -256,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)
}
/**
@@ -598,7 +588,7 @@ private module Stage1 {
) {
exists(ReturnNodeExt ret |
throughFlowNodeCand(ret, config) and
callable = ret.getEnclosingCallable() and
callable = getNodeEnclosingCallable(ret) and
kind = ret.getKind()
)
}
@@ -611,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 |
@@ -775,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) }
@@ -963,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
)
@@ -982,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)
|
@@ -1213,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
@@ -1345,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
@@ -1394,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) }
@@ -1591,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
)
@@ -1610,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)
|
@@ -1841,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
@@ -2087,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) }
@@ -2132,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(
@@ -2297,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
)
@@ -2316,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)
|
@@ -2547,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
@@ -2587,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
)
}
@@ -3116,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
@@ -3402,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)
@@ -3417,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)
@@ -3446,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)
)
}
@@ -3583,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,
@@ -3600,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()
)
}
@@ -3659,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())
}
/**
@@ -3667,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() {

View File

@@ -207,23 +207,14 @@ 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`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
simpleLocalFlowStep(node1, node2) and
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -234,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
@@ -256,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)
}
/**
@@ -598,7 +588,7 @@ private module Stage1 {
) {
exists(ReturnNodeExt ret |
throughFlowNodeCand(ret, config) and
callable = ret.getEnclosingCallable() and
callable = getNodeEnclosingCallable(ret) and
kind = ret.getKind()
)
}
@@ -611,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 |
@@ -775,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) }
@@ -963,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
)
@@ -982,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)
|
@@ -1213,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
@@ -1345,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
@@ -1394,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) }
@@ -1591,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
)
@@ -1610,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)
|
@@ -1841,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
@@ -2087,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) }
@@ -2132,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(
@@ -2297,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
)
@@ -2316,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)
|
@@ -2547,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
@@ -2587,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
)
}
@@ -3116,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
@@ -3402,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)
@@ -3417,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)
@@ -3446,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)
)
}
@@ -3583,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,
@@ -3600,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()
)
}
@@ -3659,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())
}
/**
@@ -3667,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() {

View File

@@ -207,23 +207,14 @@ 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`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
simpleLocalFlowStep(node1, node2) and
(
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -234,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
@@ -256,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)
}
/**
@@ -598,7 +588,7 @@ private module Stage1 {
) {
exists(ReturnNodeExt ret |
throughFlowNodeCand(ret, config) and
callable = ret.getEnclosingCallable() and
callable = getNodeEnclosingCallable(ret) and
kind = ret.getKind()
)
}
@@ -611,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 |
@@ -775,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) }
@@ -963,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
)
@@ -982,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)
|
@@ -1213,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
@@ -1345,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
@@ -1394,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) }
@@ -1591,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
)
@@ -1610,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)
|
@@ -1841,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
@@ -2087,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) }
@@ -2132,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(
@@ -2297,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
)
@@ -2316,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)
|
@@ -2547,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
@@ -2587,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
)
}
@@ -3116,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
@@ -3402,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)
@@ -3417,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)
@@ -3446,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)
)
}
@@ -3583,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,
@@ -3600,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()
)
}
@@ -3659,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())
}
/**
@@ -3667,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() {

View File

@@ -415,6 +415,30 @@ private module Cached {
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
}
/**
* Holds if data can flow from `fromNode` to `toNode` because they are the post-update
* nodes of some function output and input respectively, where the output and input
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
cached
predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
|
exists(DataFlowCall c |
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgumentNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -423,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
@@ -568,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() }
@@ -613,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))
}
/**
@@ -722,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]

View File

@@ -819,7 +819,15 @@ class DataFlowType extends TDataFlowType {
/** A node that performs a type cast. */
class CastNode extends Node {
CastNode() { none() }
// We include read- and store steps here to force them to be
// shown in path explanations.
// This hack is necessary, because we have included some of these
// steps as default taint steps, making them be suppressed in path
// explanations.
// We should revert this once, we can remove this steps from the
// default taint steps; this should be possible once we have
// implemented flow summaries and recursive content.
CastNode() { readStep(_, _, this) or storeStep(_, _, this) }
}
/**

View File

@@ -2074,7 +2074,11 @@ private module Django {
// TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with
// points-to and `.lookup`, which would handle `post = my_post_handler` inside class def
result = this.getAMethod() and
result.getName() = HTTP::httpVerbLower()
(
result.getName() = HTTP::httpVerbLower()
or
result.getName() = "get_redirect_url"
)
}
/**
@@ -2124,6 +2128,8 @@ private module Django {
/**
* A function that is a django route handler, meaning it handles incoming requests
* with the django framework.
*
* Most functions take a django HttpRequest as a parameter (but not all).
*/
private class DjangoRouteHandler extends Function {
DjangoRouteHandler() {
@@ -2132,6 +2138,12 @@ private module Django {
any(DjangoViewClass vc).getARequestHandler() = this
}
/**
* Gets the index of the parameter where the first routed parameter can be passed --
* that is, the one just after any possible `self` or HttpRequest parameters.
*/
int getFirstPossibleRoutedParamIndex() { result = 1 + this.getRequestParamIndex() }
/** Gets the index of the request parameter. */
int getRequestParamIndex() {
not this.isMethod() and
@@ -2145,6 +2157,26 @@ private module Django {
Parameter getRequestParam() { result = this.getArg(this.getRequestParamIndex()) }
}
/**
* A method named `get_redirect_url` on a django view class.
*
* See https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#django.views.generic.base.RedirectView.get_redirect_url
*
* Note: this function only does something on a subclass of `RedirectView`, but since
* classes can be considered django view classes without us knowing their super-classes,
* we need to consider _any_ django view class. I don't expect any problems to come from this.
*/
private class GetRedirectUrlFunction extends DjangoRouteHandler {
GetRedirectUrlFunction() {
this.getName() = "get_redirect_url" and
any(DjangoViewClass vc).getARequestHandler() = this
}
override int getFirstPossibleRoutedParamIndex() { result = 1 }
override int getRequestParamIndex() { none() }
}
/** A data-flow node that sets up a route on a server, using the django framework. */
abstract private class DjangoRouteSetup extends HTTP::Server::RouteSetup::Range, DataFlow::CfgNode {
/** Gets the data-flow node that is used as the argument for the view handler. */
@@ -2175,7 +2207,7 @@ private module Django {
// parameter. This should give us more RemoteFlowSources but could also lead to
// more FPs. If this turns out to be the wrong tradeoff, we can always change our mind.
result in [this.getArg(_), this.getArgByName(_)] and
not result = any(int i | i <= this.getRequestParamIndex() | this.getArg(i))
not result = any(int i | i < this.getFirstPossibleRoutedParamIndex() | this.getArg(i))
}
override string getFramework() { result = "Django" }
@@ -2215,7 +2247,8 @@ private module Django {
exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() |
not exists(this.getUrlPattern()) and
result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and
not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i))
not result =
any(int i | i < routeHandler.getFirstPossibleRoutedParamIndex() | routeHandler.getArg(i))
)
or
exists(string name |
@@ -2237,7 +2270,8 @@ private module Django {
exists(DjangoRouteHandler routeHandler | routeHandler = this.getARequestHandler() |
not exists(this.getUrlPattern()) and
result in [routeHandler.getArg(_), routeHandler.getArgByName(_)] and
not result = any(int i | i <= routeHandler.getRequestParamIndex() | routeHandler.getArg(i))
not result =
any(int i | i < routeHandler.getFirstPossibleRoutedParamIndex() | routeHandler.getArg(i))
)
or
exists(DjangoRouteHandler routeHandler, DjangoRouteRegex regex |
@@ -2249,7 +2283,9 @@ private module Django {
not exists(regex.getGroupName(_, _)) and
// first group will have group number 1
result =
routeHandler.getArg(routeHandler.getRequestParamIndex() + regex.getGroupNumber(_, _))
routeHandler
.getArg(routeHandler.getFirstPossibleRoutedParamIndex() - 1 +
regex.getGroupNumber(_, _))
or
result = routeHandler.getArgByName(regex.getGroupName(_, _))
)
@@ -2445,4 +2481,31 @@ private module Django {
override string getMimetypeDefault() { none() }
}
// ---------------------------------------------------------------------------
// RedirectView handling
// ---------------------------------------------------------------------------
/**
* A return from a method named `get_redirect_url` on a django view class.
*
* Note that in reality, this only does something on a subclass of `RedirectView` --
* but until API graphs makes this easy to model, I took a shortcut in modeling
* preciseness.
*
* See https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#redirectview
*/
private class DjangoRedirectViewGetRedirectUrlReturn extends HTTP::Server::HttpRedirectResponse::Range,
DataFlow::CfgNode {
DjangoRedirectViewGetRedirectUrlReturn() {
node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode()
}
override DataFlow::Node getRedirectLocation() { result = this }
override DataFlow::Node getBody() { none() }
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
override string getMimetypeDefault() { none() }
}
}

View File

@@ -351,7 +351,8 @@ module Flask {
exists(string method_name | method_name in ["get_data", "get_json"] |
// Method access
nodeFrom = request().getAUse() and
nodeTo = request().getMember(method_name).getAnImmediateUse()
nodeTo.(DataFlow::AttrRead).getObject() = nodeFrom and
nodeTo.(DataFlow::AttrRead).getAttributeName() = method_name
or
// Method call
nodeFrom = request().getMember(method_name).getAUse() and

View File

@@ -1,34 +1,39 @@
import python
import semmle.python.objects.ObjectInternal
deprecated import semmle.python.objects.ObjectInternal as OI
private import semmle.python.ApiGraphs
private predicate re_module_function(string name, int flags) {
name = "compile" and flags = 1
/**
* Gets the positional argument index containing the regular expression flags for the member of the
* `re` module with the name `name`.
*/
private int re_member_flags_arg(string name) {
name = "compile" and result = 1
or
name = "search" and flags = 2
name = "search" and result = 2
or
name = "match" and flags = 2
name = "match" and result = 2
or
name = "split" and flags = 3
name = "split" and result = 3
or
name = "findall" and flags = 2
name = "findall" and result = 2
or
name = "finditer" and flags = 2
name = "finditer" and result = 2
or
name = "sub" and flags = 4
name = "sub" and result = 4
or
name = "subn" and flags = 4
name = "subn" and result = 4
}
/**
* Gets the names and corresponding values of attributes of the `re` module that are likely to be
* Gets the names and corresponding API nodes of members of the `re` module that are likely to be
* methods taking regular expressions as arguments.
*
* This is a helper predicate that fixes a bad join order, and should not be inlined without checking
* that this is safe.
*/
pragma[nomagic]
private Value relevant_re_attr(string name) {
result = Module::named("re").attr(name) and
private API::Node relevant_re_member(string name) {
result = API::moduleImport("re").getMember(name) and
name != "escape"
}
@@ -39,24 +44,78 @@ private Value relevant_re_attr(string name) {
predicate used_as_regex(Expr s, string mode) {
(s instanceof Bytes or s instanceof Unicode) and
/* Call to re.xxx(regex, ... [mode]) */
exists(CallNode call, string name |
call.getArg(0).pointsTo(_, _, s.getAFlowNode()) and
call.getFunction().pointsTo(relevant_re_attr(name))
exists(DataFlow::CallCfgNode call, string name |
call.getArg(0).asExpr() = s and
call = relevant_re_member(name).getACall()
|
mode = "None"
or
exists(Value obj | mode = mode_from_mode_object(obj) |
exists(int flags_arg |
re_module_function(name, flags_arg) and
call.getArg(flags_arg).pointsTo(obj)
)
or
call.getArgByName("flags").pointsTo(obj)
mode = mode_from_node([call.getArg(re_member_flags_arg(name)), call.getArgByName("flags")])
)
}
/**
* Gets the canonical name for the API graph node corresponding to the `re` flag `flag`. For flags
* that have multiple names, we pick the long-form name as a canonical representative.
*/
private string canonical_name(API::Node flag) {
result in ["ASCII", "IGNORECASE", "LOCALE", "UNICODE", "MULTILINE", "TEMPLATE"] and
flag = API::moduleImport("re").getMember([result, result.prefix(1)])
or
flag = API::moduleImport("re").getMember(["DOTALL", "S"]) and result = "DOTALL"
or
flag = API::moduleImport("re").getMember(["VERBOSE", "X"]) and result = "VERBOSE"
}
/**
* A type tracker for regular expression flag names. Holds if the result is a node that may refer
* to the `re` flag with the canonical name `flag_name`
*/
private DataFlow::LocalSourceNode re_flag_tracker(string flag_name, DataFlow::TypeTracker t) {
t.start() and
exists(API::Node flag | flag_name = canonical_name(flag) and result = flag.getAUse())
or
exists(BinaryExprNode binop, DataFlow::Node operand |
operand.getALocalSource() = re_flag_tracker(flag_name, t.continue()) and
operand.asCfgNode() = binop.getAnOperand() and
(binop.getOp() instanceof BitOr or binop.getOp() instanceof Add) and
result.asCfgNode() = binop
)
or
// Due to bad performance when using normal setup with `re_flag_tracker(t2, attr_name).track(t2, t)`
// we have inlined that code and forced a join
exists(DataFlow::TypeTracker t2 |
exists(DataFlow::StepSummary summary |
re_flag_tracker_first_join(t2, flag_name, result, summary) and
t = t2.append(summary)
)
)
}
string mode_from_mode_object(Value obj) {
pragma[nomagic]
private predicate re_flag_tracker_first_join(
DataFlow::TypeTracker t2, string flag_name, DataFlow::Node res, DataFlow::StepSummary summary
) {
DataFlow::StepSummary::step(re_flag_tracker(flag_name, t2), res, summary)
}
/**
* A type tracker for regular expression flag names. Holds if the result is a node that may refer
* to the `re` flag with the canonical name `flag_name`
*/
private DataFlow::Node re_flag_tracker(string flag_name) {
re_flag_tracker(flag_name, DataFlow::TypeTracker::end()).flowsTo(result)
}
/** Gets a regular expression mode flag associated with the given data flow node. */
string mode_from_node(DataFlow::Node node) { node = re_flag_tracker(result) }
/**
* DEPRECATED 2021-02-24 -- use `mode_from_node` instead.
*
* Gets a regular expression mode flag associated with the given value.
*/
deprecated string mode_from_mode_object(Value obj) {
(
result = "DEBUG" or
result = "IGNORECASE" or
@@ -67,8 +126,8 @@ string mode_from_mode_object(Value obj) {
result = "VERBOSE"
) and
exists(int flag |
flag = Value::named("sre_constants.SRE_FLAG_" + result).(ObjectInternal).intValue() and
obj.(ObjectInternal).intValue().bitAnd(flag) = flag
flag = Value::named("sre_constants.SRE_FLAG_" + result).(OI::ObjectInternal).intValue() and
obj.(OI::ObjectInternal).intValue().bitAnd(flag) = flag
)
}

View File

@@ -1,6 +1,7 @@
/**
* Provides a library for writing QL tests whose success or failure is based on expected results
* embedded in the test source code as comments, rather than a `.expected` file.
* embedded in the test source code as comments, rather than the contents of an `.expected` file
* (in that the `.expected` file should always be empty).
*
* To add this framework to a new language:
* - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class
@@ -233,7 +234,9 @@ private string expectationPattern() {
exists(string tag, string tags, string value |
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
value = "((?:\"[^\"]*\"|'[^']*'|\\S+)*)" and
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
// For example, `b"foo"`.
value = "((?:[bru]*\"[^\"]*\"|[bru]*'[^']*'|\\S+)*)" and
result = tags + "(?:=" + value + ")?"
)
}

View File

@@ -0,0 +1 @@
semmle-extractor-options: --lang=2 --max-import-depth=1

View File

@@ -0,0 +1,3 @@
def python2_style():
from __builtin__ import open #$ use=moduleImport("builtins").getMember("open")
open("hello.txt") #$ use=moduleImport("builtins").getMember("open").getReturn()

View File

@@ -0,0 +1,30 @@
import python
import semmle.python.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
import semmle.python.ApiGraphs
class ApiUseTest extends InlineExpectationsTest {
ApiUseTest() { this = "ApiUseTest" }
override string getARelevantTag() { result = "use" }
private predicate relevant_node(API::Node a, DataFlow::Node n, Location l) {
n = a.getAUse() and l = n.getLocation()
}
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(API::Node a, DataFlow::Node n | relevant_node(a, n, location) |
tag = "use" and
// Only report the longest path on this line:
value =
max(API::Node a2, Location l2 |
relevant_node(a2, _, l2) and
l2.getFile() = location.getFile() and
l2.getStartLine() = location.getStartLine()
|
a2.getPath()
) and
element = n.toString()
)
}
}

View File

@@ -100,3 +100,42 @@ def internal():
pass
int_instance = IntMyView() #$ use=moduleImport("pflask").getMember("views").getMember("View").getASubclass().getReturn()
# Built-ins
def use_of_builtins():
for x in range(5): #$ use=moduleImport("builtins").getMember("range").getReturn()
if x < len([]): #$ use=moduleImport("builtins").getMember("len").getReturn()
print("Hello") #$ use=moduleImport("builtins").getMember("print").getReturn()
raise Exception("Farewell") #$ use=moduleImport("builtins").getMember("Exception").getReturn()
def imported_builtins():
import builtins #$ use=moduleImport("builtins")
def open(f):
return builtins.open(f) #$ MISSING: use=moduleImport("builtins").getMember("open").getReturn()
def redefine_print():
def my_print(x):
import builtins #$ use=moduleImport("builtins")
builtins.print("I'm printing", x) #$ use=moduleImport("builtins").getMember("print").getReturn()
print = my_print
print("these words")
def local_redefine_range():
range = 5
return range
def global_redefine_range():
global range
range = 6
return range #$ SPURIOUS: use=moduleImport("builtins").getMember("range")
def obscured_print():
p = print #$ use=moduleImport("builtins").getMember("print")
p("Can you see me?") #$ use=moduleImport("builtins").getMember("print").getReturn()
def python2_style():
# In Python 3, `__builtin__` has no special meaning.
from __builtin__ import open #$ use=moduleImport("__builtin__").getMember("open")
open("hello.txt") #$ use=moduleImport("__builtin__").getMember("open").getReturn()

View File

@@ -2,5 +2,5 @@ import mypkg #$ use=moduleImport("mypkg")
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
try:
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar")
except AttributeError as e:
print(e) # module 'mypkg' has no attribute 'bar'
except AttributeError as e: #$ use=moduleImport("builtins").getMember("AttributeError")
print(e) #$ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'

View File

@@ -3,8 +3,8 @@ import mypkg #$ use=moduleImport("mypkg")
print(mypkg.foo) #$ use=moduleImport("mypkg").getMember("foo") // 42
try:
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar")
except AttributeError as e:
print(e) # module 'mypkg' has no attribute 'bar'
except AttributeError as e: #$ use=moduleImport("builtins").getMember("AttributeError")
print(e) #$ use=moduleImport("builtins").getMember("print").getReturn() // module 'mypkg' has no attribute 'bar'
from mypkg import bar as _bar #$ use=moduleImport("mypkg").getMember("bar")
print(mypkg.bar) #$ use=moduleImport("mypkg").getMember("bar") // <module 'mypkg.bar' ...

View File

@@ -1,3 +1,4 @@
| response_test.py:61 | ok | get_redirect_url | foo |
| taint_test.py:8 | ok | test_taint | bar |
| taint_test.py:8 | ok | test_taint | foo |
| taint_test.py:9 | ok | test_taint | baz |

View File

@@ -1,4 +1,5 @@
from django.http.response import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, JsonResponse, HttpResponseNotFound
from django.views.generic import RedirectView
import django.shortcuts
# Not an XSS sink, since the Content-Type is not "text/html"
@@ -54,6 +55,14 @@ def redirect_shortcut(request):
return django.shortcuts.redirect(next) # $ HttpResponse HttpRedirectResponse redirectLocation=next
class CustomRedirectView(RedirectView):
def get_redirect_url(self, foo): # $ requestHandler routedParameter=foo
ensure_tainted(foo)
next = "https://example.com/{}".format(foo)
return next # $ HttpResponse HttpRedirectResponse redirectLocation=next
# Ensure that simple subclasses are still vuln to XSS
def xss__not_found(request):
return HttpResponseNotFound(request.GET.get("name")) # $HttpResponse mimetype=text/html responseBody=Attribute()

View File

@@ -15,4 +15,7 @@ urlpatterns = [
path("basic-view-handler/", views.MyBasicViewHandler.as_view()), # $routeSetup="basic-view-handler/"
path("custom-inheritance-view-handler/", views.MyViewHandlerWithCustomInheritance.as_view()), # $routeSetup="custom-inheritance-view-handler/"
path("CustomRedirectView/<foo>", views.CustomRedirectView.as_view()), # $routeSetup="CustomRedirectView/<foo>"
path("CustomRedirectView2/<foo>", views.CustomRedirectView2.as_view()), # $routeSetup="CustomRedirectView2/<foo>"
]

View File

@@ -1,5 +1,5 @@
from django.http import HttpRequest, HttpResponse
from django.views import View
from django.views.generic import View, RedirectView
from django.views.decorators.csrf import csrf_exempt
@@ -32,3 +32,16 @@ class MyViewHandlerWithCustomInheritance(MyCustomViewBaseClass):
def get(self, request: HttpRequest): # $ requestHandler
print(self.request.GET)
return HttpResponse("MyViewHandlerWithCustomInheritance: GET") # $ HttpResponse
# RedirectView
# See docs at https://docs.djangoproject.com/en/3.1/ref/class-based-views/base/#redirectview
class CustomRedirectView(RedirectView):
def get_redirect_url(self, foo): # $ requestHandler routedParameter=foo
next = "https://example.com/{}".format(foo)
return next # $ HttpResponse HttpRedirectResponse redirectLocation=next
class CustomRedirectView2(RedirectView):
url = "https://example.com/%(foo)s"

View File

@@ -1,10 +1,14 @@
edges
| test.py:21:11:21:18 | ControlFlowNode for source() | test.py:22:10:22:24 | ControlFlowNode for Attribute() |
| test.py:29:11:29:18 | ControlFlowNode for source() | test.py:33:10:33:12 | ControlFlowNode for val |
| test.py:39:15:39:17 | ControlFlowNode for arg | test.py:41:10:41:12 | ControlFlowNode for val |
| test.py:21:11:21:18 | ControlFlowNode for source() | test.py:22:10:22:22 | ControlFlowNode for Attribute |
| test.py:22:10:22:22 | ControlFlowNode for Attribute | test.py:22:10:22:24 | ControlFlowNode for Attribute() |
| test.py:29:11:29:18 | ControlFlowNode for source() | test.py:31:20:31:32 | ControlFlowNode for Attribute |
| test.py:31:20:31:32 | ControlFlowNode for Attribute | test.py:33:10:33:12 | ControlFlowNode for val |
| test.py:39:15:39:17 | ControlFlowNode for arg | test.py:40:11:40:23 | ControlFlowNode for Attribute |
| test.py:40:11:40:23 | ControlFlowNode for Attribute | test.py:41:10:41:12 | ControlFlowNode for val |
| test.py:45:11:45:18 | ControlFlowNode for source() | test.py:46:15:46:17 | ControlFlowNode for src |
| test.py:46:15:46:17 | ControlFlowNode for src | test.py:39:15:39:17 | ControlFlowNode for arg |
| test.py:52:24:52:26 | ControlFlowNode for arg | test.py:54:10:54:12 | ControlFlowNode for val |
| test.py:52:24:52:26 | ControlFlowNode for arg | test.py:53:11:53:23 | ControlFlowNode for Attribute |
| test.py:53:11:53:23 | ControlFlowNode for Attribute | test.py:54:10:54:12 | ControlFlowNode for val |
| test.py:57:33:57:35 | ControlFlowNode for arg | test.py:58:24:58:26 | ControlFlowNode for arg |
| test.py:58:24:58:26 | ControlFlowNode for arg | test.py:52:24:52:26 | ControlFlowNode for arg |
| test.py:61:33:61:35 | ControlFlowNode for arg | test.py:62:33:62:35 | ControlFlowNode for arg |
@@ -27,14 +31,18 @@ edges
| test.py:108:46:108:58 | ControlFlowNode for Attribute | test.py:102:46:102:47 | ControlFlowNode for bm |
nodes
| test.py:21:11:21:18 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:22:10:22:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:22:10:22:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:29:11:29:18 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:31:20:31:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:33:10:33:12 | ControlFlowNode for val | semmle.label | ControlFlowNode for val |
| test.py:39:15:39:17 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg |
| test.py:40:11:40:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:41:10:41:12 | ControlFlowNode for val | semmle.label | ControlFlowNode for val |
| test.py:45:11:45:18 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:46:15:46:17 | ControlFlowNode for src | semmle.label | ControlFlowNode for src |
| test.py:52:24:52:26 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg |
| test.py:53:11:53:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:54:10:54:12 | ControlFlowNode for val | semmle.label | ControlFlowNode for val |
| test.py:57:33:57:35 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg |
| test.py:58:24:58:26 | ControlFlowNode for arg | semmle.label | ControlFlowNode for arg |

View File

@@ -15,27 +15,27 @@
| taint_test.py:26 | ok | get | self.path_kwargs |
| taint_test.py:27 | ok | get | self.path_kwargs["name"] |
| taint_test.py:34 | ok | get | request |
| taint_test.py:36 | ok | get | request.uri |
| taint_test.py:37 | ok | get | request.path |
| taint_test.py:38 | ok | get | request.query |
| taint_test.py:39 | ok | get | request.full_url() |
| taint_test.py:41 | ok | get | request.remote_ip |
| taint_test.py:43 | ok | get | request.body |
| taint_test.py:45 | ok | get | request.arguments |
| taint_test.py:46 | ok | get | request.arguments["name"] |
| taint_test.py:47 | ok | get | request.arguments["name"][0] |
| taint_test.py:49 | ok | get | request.query_arguments |
| taint_test.py:50 | ok | get | request.query_arguments["name"] |
| taint_test.py:51 | ok | get | request.query_arguments["name"][0] |
| taint_test.py:53 | ok | get | request.body_arguments |
| taint_test.py:54 | ok | get | request.body_arguments["name"] |
| taint_test.py:55 | ok | get | request.body_arguments["name"][0] |
| taint_test.py:58 | ok | get | request.headers |
| taint_test.py:59 | ok | get | request.headers["header-name"] |
| taint_test.py:60 | fail | get | request.headers.get_list(..) |
| taint_test.py:61 | fail | get | request.headers.get_all() |
| taint_test.py:62 | fail | get | ListComp |
| taint_test.py:65 | ok | get | request.cookies |
| taint_test.py:66 | ok | get | request.cookies["cookie-name"] |
| taint_test.py:67 | fail | get | request.cookies["cookie-name"].key |
| taint_test.py:68 | fail | get | request.cookies["cookie-name"].value |
| taint_test.py:40 | ok | get | request.uri |
| taint_test.py:41 | ok | get | request.path |
| taint_test.py:42 | ok | get | request.query |
| taint_test.py:43 | ok | get | request.full_url() |
| taint_test.py:45 | ok | get | request.remote_ip |
| taint_test.py:47 | ok | get | request.body |
| taint_test.py:49 | ok | get | request.arguments |
| taint_test.py:50 | ok | get | request.arguments["name"] |
| taint_test.py:51 | ok | get | request.arguments["name"][0] |
| taint_test.py:53 | ok | get | request.query_arguments |
| taint_test.py:54 | ok | get | request.query_arguments["name"] |
| taint_test.py:55 | ok | get | request.query_arguments["name"][0] |
| taint_test.py:57 | ok | get | request.body_arguments |
| taint_test.py:58 | ok | get | request.body_arguments["name"] |
| taint_test.py:59 | ok | get | request.body_arguments["name"][0] |
| taint_test.py:62 | ok | get | request.headers |
| taint_test.py:63 | ok | get | request.headers["header-name"] |
| taint_test.py:64 | fail | get | request.headers.get_list(..) |
| taint_test.py:65 | fail | get | request.headers.get_all() |
| taint_test.py:66 | fail | get | ListComp |
| taint_test.py:69 | ok | get | request.cookies |
| taint_test.py:70 | ok | get | request.cookies["cookie-name"] |
| taint_test.py:71 | fail | get | request.cookies["cookie-name"].key |
| taint_test.py:72 | fail | get | request.cookies["cookie-name"].value |

View File

@@ -33,6 +33,10 @@ class TaintTest(tornado.web.RequestHandler):
# see https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest
request,
# For the URL https:://example.com/foo/bar?baz=42
# request.uri="/foo/bar?baz=42"
# request.path="/foo/bar"
# request.query="baz=42"
request.uri,
request.path,
request.query,

View File

@@ -7,5 +7,7 @@
| 50 | VERBOSE |
| 51 | UNICODE |
| 52 | UNICODE |
| 54 | DOTALL |
| 54 | VERBOSE |
| 56 | VERBOSE |
| 68 | MULTILINE |

View File

@@ -1 +0,0 @@
semmle-extractor-options: --max-import-depth=3

View File

@@ -51,7 +51,7 @@ re.compile("", flags=re.VERBOSE|re.IGNORECASE)
re.search("", None, re.UNICODE)
x = re.search("", flags=re.UNICODE)
# using addition for flags was reported as FP in https://github.com/github/codeql/issues/4707
re.compile("", re.VERBOSE+re.DOTALL) # TODO: Currently not recognized with Mode.ql
re.compile("", re.VERBOSE+re.DOTALL)
# re.X is an alias for re.VERBOSE
re.compile("", re.X)

View File

@@ -1,3 +1,5 @@
| BindToAllInterfaces_test.py:5:1:5:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
| BindToAllInterfaces_test.py:9:1:9:18 | Attribute() | '' binds a socket to all interfaces. |
| BindToAllInterfaces_test.py:17:1:17:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
| BindToAllInterfaces_test.py:21:1:21:11 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
| BindToAllInterfaces_test.py:26:1:26:20 | Attribute() | '::' binds a socket to all interfaces. |

View File

@@ -15,3 +15,12 @@ s.bind(('84.68.10.12', 8080))
# binds to all interfaces, insecure
ALL_LOCALS = "0.0.0.0"
s.bind((ALL_LOCALS, 9090))
# binds to all interfaces, insecure
tup = (ALL_LOCALS, 8080)
s.bind(tup)
# IPv6
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.bind(("::", 8080)) # NOT OK

View File

@@ -1,7 +1,9 @@
edges
| test.py:13:16:13:22 | ControlFlowNode for request | test.py:15:36:15:39 | ControlFlowNode for data |
| test.py:13:16:13:22 | ControlFlowNode for request | test.py:13:16:13:27 | ControlFlowNode for Attribute |
| test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data |
nodes
| test.py:13:16:13:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:13:16:13:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:15:36:15:39 | ControlFlowNode for data | semmle.label | ControlFlowNode for data |
#select
| test.py:15:36:15:39 | ControlFlowNode for data | test.py:13:16:13:22 | ControlFlowNode for request | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:13:16:13:22 | ControlFlowNode for request | ControlFlowNode for request |

View File

@@ -1,25 +1,40 @@
edges
| path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() |
| path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() |
| path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute |
| path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() |
| path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute |
| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() |
| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | path_injection.py:21:14:21:18 | ControlFlowNode for npath |
| path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() |
| path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:27:16:27:27 | ControlFlowNode for Attribute |
| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() |
| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | path_injection.py:31:14:31:18 | ControlFlowNode for npath |
| path_injection.py:37:16:37:22 | ControlFlowNode for request | path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() |
| path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() |
| path_injection.py:37:16:37:22 | ControlFlowNode for request | path_injection.py:37:16:37:27 | ControlFlowNode for Attribute |
| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() |
| path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:46:16:46:27 | ControlFlowNode for Attribute |
| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() |
| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | path_injection.py:48:14:48:18 | ControlFlowNode for npath |
| path_injection.py:54:16:54:22 | ControlFlowNode for request | path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() |
| path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() |
| path_injection.py:54:16:54:22 | ControlFlowNode for request | path_injection.py:54:16:54:27 | ControlFlowNode for Attribute |
| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() |
| path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:63:16:63:27 | ControlFlowNode for Attribute |
| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() |
| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | path_injection.py:65:14:65:18 | ControlFlowNode for npath |
| path_injection.py:71:16:71:22 | ControlFlowNode for request | path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() |
| path_injection.py:71:16:71:22 | ControlFlowNode for request | path_injection.py:71:16:71:27 | ControlFlowNode for Attribute |
| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() |
| path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | path_injection.py:81:14:81:17 | ControlFlowNode for path |
| path_injection.py:85:20:85:22 | ControlFlowNode for foo | path_injection.py:89:14:89:17 | ControlFlowNode for path |
| path_injection.py:94:16:94:22 | ControlFlowNode for request | path_injection.py:100:14:100:17 | ControlFlowNode for path |
| path_injection.py:105:16:105:22 | ControlFlowNode for request | path_injection.py:111:14:111:17 | ControlFlowNode for path |
| path_injection.py:116:16:116:22 | ControlFlowNode for request | path_injection.py:119:14:119:22 | ControlFlowNode for sanitized |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | path_injection.py:127:30:127:51 | ControlFlowNode for Attribute() |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | path_injection.py:129:14:129:17 | ControlFlowNode for path |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| path_injection.py:94:16:94:22 | ControlFlowNode for request | path_injection.py:94:16:94:27 | ControlFlowNode for Attribute |
| path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | path_injection.py:100:14:100:17 | ControlFlowNode for path |
| path_injection.py:105:16:105:22 | ControlFlowNode for request | path_injection.py:105:16:105:27 | ControlFlowNode for Attribute |
| path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | path_injection.py:111:14:111:17 | ControlFlowNode for path |
| path_injection.py:116:16:116:22 | ControlFlowNode for request | path_injection.py:116:16:116:27 | ControlFlowNode for Attribute |
| path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | path_injection.py:119:14:119:22 | ControlFlowNode for sanitized |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | path_injection.py:125:16:125:27 | ControlFlowNode for Attribute |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | path_injection.py:125:16:125:27 | ControlFlowNode for Attribute |
| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | path_injection.py:127:30:127:51 | ControlFlowNode for Attribute() |
| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | path_injection.py:129:14:129:17 | ControlFlowNode for path |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute |
| test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:18:9:18:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:24:9:24:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:31:9:31:16 | ControlFlowNode for source() |
@@ -38,7 +53,8 @@ edges
| test.py:46:9:46:16 | ControlFlowNode for source() | test.py:48:23:48:23 | ControlFlowNode for x |
| test.py:48:13:48:24 | ControlFlowNode for normalize() | test.py:49:14:49:14 | ControlFlowNode for y |
| test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x |
| test_chaining.py:9:12:9:18 | ControlFlowNode for request | test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test_chaining.py:9:12:9:18 | ControlFlowNode for request | test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:20:9:20:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:28:9:28:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:41:9:41:16 | ControlFlowNode for source() |
@@ -53,41 +69,56 @@ edges
| test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | test_chaining.py:45:14:45:14 | ControlFlowNode for z |
nodes
| path_injection.py:12:16:12:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:19:16:19:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:20:13:20:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:21:14:21:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:27:16:27:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:27:16:27:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:28:13:28:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:31:14:31:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:37:16:37:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:37:16:37:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:38:13:38:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:46:16:46:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:46:16:46:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:47:13:47:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:48:14:48:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:54:16:54:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:54:16:54:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:55:13:55:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:63:16:63:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:63:16:63:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:64:13:64:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:65:14:65:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:71:16:71:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:71:16:71:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:72:13:72:63 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:78:20:78:25 | ControlFlowNode for foo_id | semmle.label | ControlFlowNode for foo_id |
| path_injection.py:81:14:81:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:85:20:85:22 | ControlFlowNode for foo | semmle.label | ControlFlowNode for foo |
| path_injection.py:89:14:89:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:94:16:94:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:94:16:94:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:100:14:100:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:105:16:105:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:105:16:105:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:111:14:111:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| path_injection.py:116:16:116:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:116:16:116:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:119:14:119:22 | ControlFlowNode for sanitized | semmle.label | ControlFlowNode for sanitized |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:125:16:125:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:125:16:125:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:127:30:127:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:129:14:129:17 | ControlFlowNode for path | semmle.label | ControlFlowNode for path |
| test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:12:15:12:15 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
@@ -107,6 +138,7 @@ nodes
| test.py:48:23:48:23 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:49:14:49:14 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test_chaining.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test_chaining.py:14:15:14:15 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |

View File

@@ -1,15 +1,17 @@
edges
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr |
nodes
| command_injection.py:18:13:18:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |

View File

@@ -1,38 +1,54 @@
edges
| command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr |
| command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd |
| command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr |
| command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command |
| command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command |
| command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr |
| command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr |
| command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute |
| command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr |
| command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:25:11:25:22 | ControlFlowNode for Attribute |
| command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | command_injection.py:26:23:26:25 | ControlFlowNode for cmd |
| command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:31:13:31:24 | ControlFlowNode for Attribute |
| command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr |
| command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:38:15:38:26 | ControlFlowNode for Attribute |
| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:41:15:41:21 | ControlFlowNode for command |
| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | command_injection.py:42:15:42:21 | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:54:15:54:26 | ControlFlowNode for Attribute |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:55:15:55:21 | ControlFlowNode for command |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:56:14:56:20 | ControlFlowNode for command |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:57:21:57:27 | ControlFlowNode for command |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:58:27:58:33 | ControlFlowNode for command |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | command_injection.py:59:20:59:26 | ControlFlowNode for command |
| command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:71:12:71:23 | ControlFlowNode for Attribute |
| command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr |
| command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute |
| command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr |
nodes
| command_injection.py:11:13:11:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:25:11:25:17 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:25:11:25:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| command_injection.py:31:13:31:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:31:13:31:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:38:15:38:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:38:15:38:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:41:15:41:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:42:15:42:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:54:15:54:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:54:15:54:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:55:15:55:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:56:14:56:20 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:57:21:57:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:58:27:58:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:59:20:59:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:71:12:71:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:71:12:71:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:78:12:78:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
#select
| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | a user-provided value |

View File

@@ -1,13 +1,19 @@
edges
| reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr |
| reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() |
| reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() |
| reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute |
| reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr |
| reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute |
| reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() |
| reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute |
| reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() |
nodes
| reflected_xss.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| reflected_xss.py:21:23:21:29 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| reflected_xss.py:27:23:27:29 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
#select
| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | a user-provided value |

View File

@@ -1,14 +1,18 @@
edges
| code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd |
| code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name |
| code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:7:10:7:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:8:10:8:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:10:10:10:12 | ControlFlowNode for cmd |
| code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:18:16:18:27 | ControlFlowNode for Attribute |
| code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name |
nodes
| code_injection.py:6:12:6:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| code_injection.py:7:10:7:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code |
| code_injection.py:8:10:8:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code |
| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| code_injection.py:18:16:18:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | semmle.label | ControlFlowNode for obj_name |
#select
| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | $@ flows to here and is interpreted as code. | code_injection.py:6:12:6:18 | ControlFlowNode for request | A user-provided value |

View File

@@ -2,3 +2,4 @@
| test.py:25:1:25:20 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
| test.py:29:1:29:20 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
| test.py:37:1:37:18 | ControlFlowNode for runapp() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |
| test.py:42:1:42:35 | ControlFlowNode for Attribute() | A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger. |

View File

@@ -0,0 +1 @@
ALWAYS_TRUE = True

View File

@@ -22,11 +22,11 @@ app.notrun(debug=True)
DEBUG = True
app.run(debug=DEBUG)
app.run(debug=DEBUG) # NOT OK
DEBUG = 1
app.run(debug=DEBUG)
app.run(debug=DEBUG) # NOT OK
if False:
app.run(debug=True)
@@ -34,4 +34,17 @@ if False:
runapp = app.run
runapp(debug=True)
runapp(debug=True) # NOT OK
# imports from other module
import settings
app.run(debug=settings.ALWAYS_TRUE) # NOT OK
# depending on environment values
import os
DEPENDS_ON_ENV = os.environ["ENV"] == "dev"
app.run(debug=DEPENDS_ON_ENV) # OK

View File

@@ -1 +0,0 @@
semmle-extractor-options: -p ../lib/ --max-import-depth=3

View File

@@ -1,10 +1,12 @@
edges
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload |
nodes
| unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |

View File

@@ -1,28 +1,44 @@
edges
| test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target |
| test.py:30:17:30:23 | ControlFlowNode for request | test.py:32:21:32:24 | ControlFlowNode for safe |
| test.py:37:17:37:23 | ControlFlowNode for request | test.py:39:21:39:24 | ControlFlowNode for safe |
| test.py:44:17:44:23 | ControlFlowNode for request | test.py:46:21:46:24 | ControlFlowNode for safe |
| test.py:60:17:60:23 | ControlFlowNode for request | test.py:62:21:62:26 | ControlFlowNode for unsafe |
| test.py:67:17:67:23 | ControlFlowNode for request | test.py:69:21:69:26 | ControlFlowNode for unsafe |
| test.py:74:17:74:23 | ControlFlowNode for request | test.py:76:21:76:26 | ControlFlowNode for unsafe |
| test.py:81:17:81:23 | ControlFlowNode for request | test.py:83:21:83:26 | ControlFlowNode for unsafe |
| test.py:7:14:7:20 | ControlFlowNode for request | test.py:7:14:7:25 | ControlFlowNode for Attribute |
| test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target |
| test.py:30:17:30:23 | ControlFlowNode for request | test.py:30:17:30:28 | ControlFlowNode for Attribute |
| test.py:30:17:30:28 | ControlFlowNode for Attribute | test.py:32:21:32:24 | ControlFlowNode for safe |
| test.py:37:17:37:23 | ControlFlowNode for request | test.py:37:17:37:28 | ControlFlowNode for Attribute |
| test.py:37:17:37:28 | ControlFlowNode for Attribute | test.py:39:21:39:24 | ControlFlowNode for safe |
| test.py:44:17:44:23 | ControlFlowNode for request | test.py:44:17:44:28 | ControlFlowNode for Attribute |
| test.py:44:17:44:28 | ControlFlowNode for Attribute | test.py:46:21:46:24 | ControlFlowNode for safe |
| test.py:60:17:60:23 | ControlFlowNode for request | test.py:60:17:60:28 | ControlFlowNode for Attribute |
| test.py:60:17:60:28 | ControlFlowNode for Attribute | test.py:62:21:62:26 | ControlFlowNode for unsafe |
| test.py:67:17:67:23 | ControlFlowNode for request | test.py:67:17:67:28 | ControlFlowNode for Attribute |
| test.py:67:17:67:28 | ControlFlowNode for Attribute | test.py:69:21:69:26 | ControlFlowNode for unsafe |
| test.py:74:17:74:23 | ControlFlowNode for request | test.py:74:17:74:28 | ControlFlowNode for Attribute |
| test.py:74:17:74:28 | ControlFlowNode for Attribute | test.py:76:21:76:26 | ControlFlowNode for unsafe |
| test.py:81:17:81:23 | ControlFlowNode for request | test.py:81:17:81:28 | ControlFlowNode for Attribute |
| test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:83:21:83:26 | ControlFlowNode for unsafe |
nodes
| test.py:7:14:7:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:7:14:7:25 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:8:21:8:26 | ControlFlowNode for target | semmle.label | ControlFlowNode for target |
| test.py:30:17:30:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:30:17:30:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:32:21:32:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe |
| test.py:37:17:37:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:37:17:37:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:39:21:39:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe |
| test.py:44:17:44:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:44:17:44:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:46:21:46:24 | ControlFlowNode for safe | semmle.label | ControlFlowNode for safe |
| test.py:60:17:60:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:60:17:60:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:62:21:62:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe |
| test.py:67:17:67:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:67:17:67:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:69:21:69:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe |
| test.py:74:17:74:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:74:17:74:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:76:21:76:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe |
| test.py:81:17:81:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| test.py:81:17:81:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe |
#select
| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection due to $@. | test.py:7:14:7:20 | ControlFlowNode for request | A user-provided value |