Date: Thu, 22 Apr 2021 14:47:33 +0200
Subject: [PATCH 079/550] Python: Say salting is not part of
py/weak-sensitive-data-hashing
---
python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.qhelp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.qhelp b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.qhelp
index 05c727f0815..1d7b5a4f456 100644
--- a/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.qhelp
+++ b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.qhelp
@@ -25,7 +25,8 @@
In cases with a limited input space, such as for passwords, the hash
function also needs to be computationally expensive to be resistant to
- brute-force attacks.
+ brute-force attacks. Passwords should also have an unique salt applied
+ before hashing, but that is not considered by this query.
From b82209964a74669766476c6be7619efedafa18a8 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 14 Apr 2021 13:55:01 +0200
Subject: [PATCH 080/550] Python: Add change-note for new weak crypto queries
---
python/change-notes/2021-04-09-split-weak-crypto-query.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 python/change-notes/2021-04-09-split-weak-crypto-query.md
diff --git a/python/change-notes/2021-04-09-split-weak-crypto-query.md b/python/change-notes/2021-04-09-split-weak-crypto-query.md
new file mode 100644
index 00000000000..221b2ea07df
--- /dev/null
+++ b/python/change-notes/2021-04-09-split-weak-crypto-query.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* Updated the _Use of a broken or weak cryptographic algorithm_ (`py/weak-cryptographic-algorithm`) query, so it alerts on any use of a weak cryptographic non-hashing algorithm. Introduced a new query _Use of a broken or weak cryptographic hashing algorithm on sensitive data_ (`py/weak-sensitive-data-hashing`) to handle weak cryptographic hashing algorithms, which only alerts when used on sensitive data.
From 222c087e8c2560a58579c3f5fb1ea1405bb23532 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Thu, 22 Apr 2021 15:22:08 +0200
Subject: [PATCH 081/550] Python: Remove type-tracking performance workaround
Since we shouldn't need it anymore (yay)
---
.../semmle/python/frameworks/Cryptography.qll | 68 ++-----------------
.../src/semmle/python/frameworks/Stdlib.qll | 16 +----
2 files changed, 5 insertions(+), 79 deletions(-)
diff --git a/python/ql/src/semmle/python/frameworks/Cryptography.qll b/python/ql/src/semmle/python/frameworks/Cryptography.qll
index bc7bdc0109f..5ad6b9200c2 100644
--- a/python/ql/src/semmle/python/frameworks/Cryptography.qll
+++ b/python/ql/src/semmle/python/frameworks/Cryptography.qll
@@ -206,22 +206,7 @@ private module CryptographyModel {
]
)
or
- // Due to bad performance when using normal setup with `cipherInstance(t2, algorithmName).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- cipherInstance_first_join(t2, algorithmName, result, summary) and
- t = t2.append(summary)
- )
- )
- }
-
- pragma[nomagic]
- private predicate cipherInstance_first_join(
- DataFlow::TypeTracker t2, string algorithmName, DataFlow::Node res,
- DataFlow::StepSummary summary
- ) {
- DataFlow::StepSummary::step(cipherInstance(t2, algorithmName), res, summary)
+ exists(DataFlow::TypeTracker t2 | result = cipherInstance(t2, algorithmName).track(t2, t))
}
/** Gets a reference to the encryptor of a Cipher instance using algorithm with `algorithmName`. */
@@ -233,22 +218,7 @@ private module CryptographyModel {
attr.getObject() = cipherInstance(algorithmName)
)
or
- // Due to bad performance when using normal setup with `cipherEncryptor(t2, algorithmName).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- cipherEncryptor_first_join(t2, algorithmName, result, summary) and
- t = t2.append(summary)
- )
- )
- }
-
- pragma[nomagic]
- private predicate cipherEncryptor_first_join(
- DataFlow::TypeTracker t2, string algorithmName, DataFlow::Node res,
- DataFlow::StepSummary summary
- ) {
- DataFlow::StepSummary::step(cipherEncryptor(t2, algorithmName), res, summary)
+ exists(DataFlow::TypeTracker t2 | result = cipherEncryptor(t2, algorithmName).track(t2, t))
}
/** Gets a reference to the dncryptor of a Cipher instance using algorithm with `algorithmName`. */
@@ -260,22 +230,7 @@ private module CryptographyModel {
attr.getObject() = cipherInstance(algorithmName)
)
or
- // Due to bad performance when using normal setup with `cipherDecryptor(t2, algorithmName).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- cipherDecryptor_first_join(t2, algorithmName, result, summary) and
- t = t2.append(summary)
- )
- )
- }
-
- pragma[nomagic]
- private predicate cipherDecryptor_first_join(
- DataFlow::TypeTracker t2, string algorithmName, DataFlow::Node res,
- DataFlow::StepSummary summary
- ) {
- DataFlow::StepSummary::step(cipherDecryptor(t2, algorithmName), res, summary)
+ exists(DataFlow::TypeTracker t2 | result = cipherDecryptor(t2, algorithmName).track(t2, t))
}
}
@@ -362,22 +317,7 @@ private module CryptographyModel {
]
)
or
- // Due to bad performance when using normal setup with `hashInstance(t2, algorithmName).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- hashInstance_first_join(t2, algorithmName, result, summary) and
- t = t2.append(summary)
- )
- )
- }
-
- pragma[nomagic]
- private predicate hashInstance_first_join(
- DataFlow::TypeTracker t2, string algorithmName, DataFlow::Node res,
- DataFlow::StepSummary summary
- ) {
- DataFlow::StepSummary::step(hashInstance(t2, algorithmName), res, summary)
+ exists(DataFlow::TypeTracker t2 | result = hashInstance(t2, algorithmName).track(t2, t))
}
/** Gets a reference to a Hash instance using algorithm with `algorithmName`. */
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index 5f4a2d22adb..fd7dba70898 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -886,21 +886,7 @@ private DataFlow::LocalSourceNode hashlibNewResult(DataFlow::TypeTracker t, stri
t.start() and
result = hashlibNewCall(algorithmName)
or
- // Due to bad performance when using normal setup with `hashlibNewResult(t2, algorithmName).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- hashlibNewResult_first_join(t2, algorithmName, result, summary) and
- t = t2.append(summary)
- )
- )
-}
-
-pragma[nomagic]
-private predicate hashlibNewResult_first_join(
- DataFlow::TypeTracker t2, string algorithmName, DataFlow::Node res, DataFlow::StepSummary summary
-) {
- DataFlow::StepSummary::step(hashlibNewResult(t2, algorithmName), res, summary)
+ exists(DataFlow::TypeTracker t2 | result = hashlibNewResult(t2, algorithmName).track(t2, t))
}
/** Gets a reference to the result of calling `hashlib.new` with `algorithmName` as the first argument. */
From f9383a31bf83143b8465e5b653fc44cc4586f597 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Thu, 22 Apr 2021 15:58:28 +0200
Subject: [PATCH 082/550] Python: Fix BrokenCryptoAlgorithm.qhelp
---
python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp
index 5d18f6dd5d3..1b26d30e0fe 100644
--- a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp
+++ b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp
@@ -46,10 +46,10 @@
NOTICE: the original
- pycrypto
+ pycrypto
PyPI package that provided the Crypto module is not longer
actively maintained, so you should use the
- pycryptodome
+ pycryptodome
PyPI package instead (which has a compatible API).
From ad12f383d95b80549ced0938a6cb858fda029766 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Thu, 15 Apr 2021 16:54:00 +0100
Subject: [PATCH 083/550] JS: Reduce reliance on RouteHandler in Express model
---
.../semmle/javascript/frameworks/Express.qll | 178 +++++++++---------
1 file changed, 84 insertions(+), 94 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll
index 17bfed8afda..57bca07d13b 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll
@@ -390,7 +390,7 @@ module Express {
}
/** An Express response source. */
- abstract private class ResponseSource extends HTTP::Servers::ResponseSource { }
+ abstract class ResponseSource extends HTTP::Servers::ResponseSource { }
/**
* An Express response source, that is, the response parameter of a
@@ -421,7 +421,7 @@ module Express {
}
/** An Express request source. */
- abstract private class RequestSource extends HTTP::Servers::RequestSource { }
+ abstract class RequestSource extends HTTP::Servers::RequestSource { }
/**
* An Express request source, that is, the request parameter of a
@@ -465,73 +465,98 @@ module Express {
* Gets a reference to the "query" object from a request-object originating from route-handler `rh`.
*/
DataFlow::SourceNode getAQueryObjectReference(DataFlow::TypeTracker t, RouteHandler rh) {
- t.startInProp("query") and
- result = rh.getARequestSource()
- or
- exists(DataFlow::TypeTracker t2 | result = getAQueryObjectReference(t2, rh).track(t2, t))
+ result = queryRef(rh.getARequestSource(), t)
}
/**
* Gets a reference to the "params" object from a request-object originating from route-handler `rh`.
*/
DataFlow::SourceNode getAParamsObjectReference(DataFlow::TypeTracker t, RouteHandler rh) {
- t.startInProp("params") and
- result = rh.getARequestSource()
+ result = paramsRef(rh.getARequestSource(), t)
+ }
+
+ /** The input parameter to an `app.param()` route handler. */
+ private class ParamHandlerInputAccess extends HTTP::RequestInputAccess {
+ RouteHandler rh;
+
+ ParamHandlerInputAccess() {
+ exists(RouteSetup setup | rh = setup.getARouteHandler() |
+ this = DataFlow::parameterNode(rh.getRouteHandlerParameter("parameter"))
+ )
+ }
+
+ override HTTP::RouteHandler getRouteHandler() { result = rh }
+
+ override string getKind() { result = "parameter" }
+ }
+
+ /** Gets a data flow node referring to `req.query`. */
+ private DataFlow::SourceNode queryRef(RequestSource req, DataFlow::TypeTracker t) {
+ t.start() and
+ result = req.ref().getAPropertyRead("query")
or
- exists(DataFlow::TypeTracker t2 | result = getAParamsObjectReference(t2, rh).track(t2, t))
+ exists(DataFlow::TypeTracker t2 | result = queryRef(req, t2).track(t2, t))
+ }
+
+ /** Gets a data flow node referring to `req.query`. */
+ private DataFlow::SourceNode queryRef(RequestSource req) {
+ result = queryRef(req, DataFlow::TypeTracker::end())
+ }
+
+ /** Gets a data flow node referring to `req.params`. */
+ private DataFlow::SourceNode paramsRef(RequestSource req, DataFlow::TypeTracker t) {
+ t.start() and
+ result = req.ref().getAPropertyRead("params")
+ or
+ exists(DataFlow::TypeTracker t2 | result = paramsRef(req, t2).track(t2, t))
+ }
+
+ /** Gets a data flow node referring to `req.params`. */
+ private DataFlow::SourceNode paramsRef(RequestSource req) {
+ result = paramsRef(req, DataFlow::TypeTracker::end())
}
/**
* An access to a user-controlled Express request input.
*/
class RequestInputAccess extends HTTP::RequestInputAccess {
- RouteHandler rh;
+ RequestSource request;
string kind;
RequestInputAccess() {
kind = "parameter" and
- this =
- [
- getAQueryObjectReference(DataFlow::TypeTracker::end(), rh),
- getAParamsObjectReference(DataFlow::TypeTracker::end(), rh)
- ].getAPropertyRead()
+ this = [queryRef(request), paramsRef(request)].getAPropertyRead()
or
- exists(DataFlow::SourceNode request | request = rh.getARequestSource().ref() |
+ exists(DataFlow::SourceNode ref | ref = request.ref() |
kind = "parameter" and
- this = request.getAMethodCall("param")
+ this = ref.getAMethodCall("param")
or
// `req.originalUrl`
kind = "url" and
- this = request.getAPropertyRead("originalUrl")
+ this = ref.getAPropertyRead("originalUrl")
or
// `req.cookies`
kind = "cookie" and
- this = request.getAPropertyRead("cookies")
+ this = ref.getAPropertyRead("cookies")
or
// `req.files`, treated the same as `req.body`.
// `express-fileupload` uses .files, and `multer` uses .files or .file
kind = "body" and
- this = request.getAPropertyRead(["files", "file"])
- )
- or
- kind = "body" and
- this.asExpr() = rh.getARequestBodyAccess()
- or
- // `value` in `router.param('foo', (req, res, next, value) => { ... })`
- kind = "parameter" and
- exists(RouteSetup setup | rh = setup.getARouteHandler() |
- this = DataFlow::parameterNode(rh.getRouteHandlerParameter("parameter"))
+ this = ref.getAPropertyRead(["files", "file"])
+ or
+ kind = "body" and
+ this = ref.getAPropertyRead("body")
)
}
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = request.getRouteHandler() }
override string getKind() { result = kind }
override predicate isUserControlledObject() {
kind = "body" and
exists(ExpressLibraries::BodyParser bodyParser, RouteHandlerExpr expr |
- expr.getBody() = rh and
+ expr.getBody() = request.getRouteHandler() and
bodyParser.producesUserControlledObjects() and
bodyParser.flowsToExpr(expr.getAMatchingAncestor())
)
@@ -542,13 +567,11 @@ module Express {
forall(ExpressLibraries::BodyParser bodyParser | bodyParser.producesUserControlledObjects())
or
kind = "parameter" and
- exists(DataFlow::Node request | request = DataFlow::valueNode(rh.getARequestExpr()) |
- this.(DataFlow::MethodCallNode).calls(request, "param")
- )
+ this = request.ref().getAMethodCall("param")
or
// `req.query.name`
kind = "parameter" and
- this = getAQueryObjectReference(DataFlow::TypeTracker::end(), rh).getAPropertyRead()
+ this = queryRef(request).getAPropertyRead()
}
}
@@ -556,29 +579,14 @@ module Express {
* An access to a header on an Express request.
*/
private class RequestHeaderAccess extends HTTP::RequestHeaderAccess {
- RouteHandler rh;
+ RequestSource request;
RequestHeaderAccess() {
- exists(DataFlow::Node request | request = DataFlow::valueNode(rh.getARequestExpr()) |
- exists(string methodName |
- // `req.get(...)` or `req.header(...)`
- this.(DataFlow::MethodCallNode).calls(request, methodName)
- |
- methodName = "get" or
- methodName = "header"
- )
- or
- exists(DataFlow::PropRead headers |
- // `req.headers.name`
- headers.accesses(request, "headers") and
- this = headers.getAPropertyRead()
- )
- or
- exists(string propName | propName = "host" or propName = "hostname" |
- // `req.host` and `req.hostname` are derived from headers
- this.(DataFlow::PropRead).accesses(request, propName)
- )
- )
+ this = request.ref().getAMethodCall(["get", "header"])
+ or
+ this = request.ref().getAPropertyRead("headers").getAPropertyRead()
+ or
+ this = request.ref().getAPropertyRead(["host", "hostname"])
}
override string getAHeaderName() {
@@ -591,7 +599,7 @@ module Express {
)
}
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = request.getRouteHandler() }
override string getKind() { result = "header" }
}
@@ -599,14 +607,7 @@ module Express {
/**
* HTTP headers created by Express calls
*/
- abstract private class ExplicitHeader extends HTTP::ExplicitHeaderDefinition {
- Expr response;
-
- /**
- * Gets the response expression that this header is set on.
- */
- Expr getResponse() { result = response }
- }
+ abstract private class ExplicitHeader extends HTTP::ExplicitHeaderDefinition { }
/**
* Holds if `e` is an HTTP request object.
@@ -635,16 +636,13 @@ module Express {
* An invocation of the `redirect` method of an HTTP response object.
*/
private class RedirectInvocation extends HTTP::RedirectInvocation, MethodCallExpr {
- RouteHandler rh;
+ ResponseSource response;
- RedirectInvocation() {
- getReceiver() = rh.getAResponseExpr() and
- getMethodName() = "redirect"
- }
+ RedirectInvocation() { this = response.ref().getAMethodCall("redirect").asExpr() }
override Expr getUrlArgument() { result = getLastArgument() }
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
/**
@@ -662,21 +660,18 @@ module Express {
* An invocation of the `set` or `header` method on an HTTP response object that
* sets multiple headers.
*/
- class SetMultipleHeaders extends ExplicitHeader, DataFlow::ValueNode {
- override MethodCallExpr astNode;
- RouteHandler rh;
+ class SetMultipleHeaders extends ExplicitHeader, DataFlow::MethodCallNode {
+ ResponseSource response;
SetMultipleHeaders() {
- astNode.getReceiver() = rh.getAResponseExpr() and
- response = astNode.getReceiver() and
- astNode.getMethodName() = any(string n | n = "set" or n = "header") and
- astNode.getNumArgument() = 1
+ this = response.ref().getAMethodCall(["set", "header"]) and
+ getNumArgument() = 1
}
/**
* Gets a reference to the multiple headers object that is to be set.
*/
- private DataFlow::SourceNode getAHeaderSource() { result.flowsToExpr(astNode.getArgument(0)) }
+ private DataFlow::SourceNode getAHeaderSource() { result.flowsTo(getArgument(0)) }
override predicate definesExplicitly(string headerName, Expr headerValue) {
exists(string header |
@@ -685,7 +680,7 @@ module Express {
)
}
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
override Expr getNameExpr() {
exists(DataFlow::PropWrite write | getAHeaderSource().getAPropertyWrite() = write |
@@ -705,31 +700,26 @@ module Express {
* An argument passed to the `send` or `end` method of an HTTP response object.
*/
private class ResponseSendArgument extends HTTP::ResponseSendArgument {
- RouteHandler rh;
+ ResponseSource response;
- ResponseSendArgument() {
- exists(MethodCallExpr mce |
- mce.calls(rh.getAResponseExpr(), "send") and
- this = mce.getArgument(0)
- )
- }
+ ResponseSendArgument() { this = response.ref().getAMethodCall("send").getArgument(0).asExpr() }
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
/**
* An invocation of the `cookie` method on an HTTP response object.
*/
class SetCookie extends HTTP::CookieDefinition, MethodCallExpr {
- RouteHandler rh;
+ ResponseSource response;
- SetCookie() { calls(rh.getAResponseExpr(), "cookie") }
+ SetCookie() { this = response.ref().getAMethodCall("cookie").asExpr() }
override Expr getNameArgument() { result = getArgument(0) }
override Expr getValueArgument() { result = getArgument(1) }
- override RouteHandler getRouteHandler() { result = rh }
+ override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
/**
@@ -750,11 +740,11 @@ module Express {
* An object passed to the `render` method of an HTTP response object.
*/
class TemplateObjectInput extends DataFlow::Node {
- RouteHandler rh;
+ ResponseSource response;
TemplateObjectInput() {
exists(DataFlow::MethodCallNode render |
- render.calls(rh.getAResponseExpr().flow(), "render") and
+ render = response.ref().getAMethodCall("render") and
this = render.getArgument(1)
)
}
@@ -762,7 +752,7 @@ module Express {
/**
* Gets the route handler that uses this object.
*/
- RouteHandler getRouteHandler() { result = rh }
+ RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
/**
From 822d4525af952dd75d6d0fe7c28ad2e7c034ceae Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Thu, 15 Apr 2021 13:58:43 +0100
Subject: [PATCH 084/550] JS: Drive-by change in LogInjection
---
.../semmle/javascript/security/dataflow/LogInjection.qll | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll
index fa70ae3f965..265b978d4a3 100644
--- a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll
+++ b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll
@@ -67,4 +67,11 @@ module LogInjection {
class HtmlSanitizer extends Sanitizer {
HtmlSanitizer() { this instanceof HtmlSanitizerCall }
}
+
+ /**
+ * A call to `JSON.stringify` or similar, seen as sanitizing log output.
+ */
+ class JsonStringifySanitizer extends Sanitizer {
+ JsonStringifySanitizer() { this = any(JsonStringifyCall c).getOutput() }
+ }
}
From 109d1ad27fd326680cebb682f5f10a4504c10af5 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Thu, 15 Apr 2021 14:09:58 +0100
Subject: [PATCH 085/550] JS: Model fs.promises
---
javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll | 3 +++
1 file changed, 3 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll
index bb9b0870a8b..840e9ea9b78 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll
@@ -465,6 +465,9 @@ module NodeJSLib {
) and
t.start()
or
+ t.start() and
+ result = DataFlow::moduleMember("fs", "promises")
+ or
exists(DataFlow::TypeTracker t2, DataFlow::SourceNode pred | pred = fsModule(t2) |
result = pred.track(t2, t)
or
From 671e968936d78437a93b2689efe6599f08d24450 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Thu, 15 Apr 2021 16:54:11 +0100
Subject: [PATCH 086/550] JS: Model NestJS
---
javascript/ql/src/javascript.qll | 2 +
.../src/semmle/javascript/dataflow/Nodes.qll | 3 +
.../javascript/dataflow/TaintTracking.qll | 3 +-
.../javascript/frameworks/ClassValidator.qll | 67 +++
.../src/semmle/javascript/frameworks/Nest.qll | 443 ++++++++++++++++++
.../frameworks/Nest/Consistency.expected | 0
.../frameworks/Nest/Consistency.ql | 3 +
.../frameworks/Nest/global/app.ts | 10 +
.../frameworks/Nest/global/validation.ts | 15 +
.../frameworks/Nest/local/customDecorator.ts | 26 +
.../frameworks/Nest/local/customPipe.ts | 50 ++
.../frameworks/Nest/local/routes.ts | 74 +++
.../frameworks/Nest/local/validation.ts | 51 ++
.../frameworks/Nest/test.expected | 94 ++++
.../library-tests/frameworks/Nest/test.ql | 19 +
.../frameworks/Nest/tsconfig.json | 6 +
16 files changed, 865 insertions(+), 1 deletion(-)
create mode 100644 javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll
create mode 100644 javascript/ql/src/semmle/javascript/frameworks/Nest.qll
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/Consistency.expected
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/Consistency.ql
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/global/app.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/global/validation.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/local/customDecorator.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/local/customPipe.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/local/routes.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/local/validation.ts
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/test.expected
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/test.ql
create mode 100644 javascript/ql/test/library-tests/frameworks/Nest/tsconfig.json
diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll
index b565a7cd21f..3818570c833 100644
--- a/javascript/ql/src/javascript.qll
+++ b/javascript/ql/src/javascript.qll
@@ -75,6 +75,7 @@ import semmle.javascript.frameworks.Babel
import semmle.javascript.frameworks.Cheerio
import semmle.javascript.frameworks.ComposedFunctions
import semmle.javascript.frameworks.Classnames
+import semmle.javascript.frameworks.ClassValidator
import semmle.javascript.frameworks.ClientRequests
import semmle.javascript.frameworks.ClosureLibrary
import semmle.javascript.frameworks.CookieLibraries
@@ -98,6 +99,7 @@ import semmle.javascript.frameworks.Logging
import semmle.javascript.frameworks.HttpFrameworks
import semmle.javascript.frameworks.HttpProxy
import semmle.javascript.frameworks.Markdown
+import semmle.javascript.frameworks.Nest
import semmle.javascript.frameworks.Next
import semmle.javascript.frameworks.NoSQL
import semmle.javascript.frameworks.PkgCloud
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
index 9c8d13582c3..5a110f44ff8 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
@@ -47,6 +47,9 @@ class ParameterNode extends DataFlow::SourceNode {
/** Holds if this parameter is a rest parameter. */
predicate isRestParameter() { p.isRestParameter() }
+
+ /** Gets the data flow node for an expression that is applied to this decorator. */
+ DataFlow::Node getADecorator() { result = getParameter().getADecorator().getExpression().flow() }
}
/**
diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
index 251a691501e..1a642d980bd 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll
@@ -550,7 +550,8 @@ module TaintTracking {
// reading from a tainted object yields a tainted result
succ.(DataFlow::PropRead).getBase() = pred and
not AccessPath::DominatingPaths::hasDominatingWrite(succ) and
- not isSafeClientSideUrlProperty(succ)
+ not isSafeClientSideUrlProperty(succ) and
+ not ClassValidator::isAccessToSanitizedField(succ)
or
// iterating over a tainted iterator taints the loop variable
exists(ForOfStmt fos |
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll
new file mode 100644
index 00000000000..f0e95d0583d
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll
@@ -0,0 +1,67 @@
+/**
+ * Provides predicates for reasoning about sanitization via the `class-validator` library.
+ */
+
+import javascript
+
+/**
+ * Provides predicates for reasoning about sanitization via the `class-validator` library.
+ */
+module ClassValidator {
+ /**
+ * Holds if the decorator with the given name does not sanitize the input, for the purpose of taint tracking.
+ */
+ bindingset[name]
+ private predicate isSanitizingDecoratorName(string name) {
+ // Most decorators do sanitize the input, so only list those that don't.
+ not name =
+ [
+ "IsDefined", "IsOptional", "NotEquals", "IsNotEmpty", "IsNotIn", "IsString", "IsArray",
+ "Contains", "NotContains", "IsAscii", "IsByteLength", "IsDataURI", "IsFQDN", "IsJSON",
+ "IsJWT", "IsObject", "IsNotEmptyObject", "IsLowercase", "IsSurrogatePair", "IsUrl",
+ "IsUppercase", "Length", "MinLength", "MaxLength", "ArrayContains", "ArrayNotContains",
+ "ArrayNotEmpty", "ArrayMinSize", "ArrayMaxSize", "ArrayUnique", "Allow", "ValidateNested",
+ "Validate",
+ // Consider "Matches" to be non-sanitizing as it is special-cased below
+ "Matches"
+ ]
+ }
+
+ /** Holds if the given call is a decorator that sanitizes values for the purpose of taint tracking, such as `IsBoolean()`. */
+ API::CallNode sanitizingDecorator() {
+ exists(string name | result = API::moduleImport("class-validator").getMember(name).getACall() |
+ isSanitizingDecoratorName(name)
+ or
+ name = "Matches" and
+ RegExp::isGenericRegExpSanitizer(RegExp::getRegExpFromNode(result.getArgument(0)), true)
+ )
+ }
+
+ /** Holds if the given field has a decorator that sanitizes its value for the purpose of taint tracking. */
+ predicate isFieldSanitizedByDecorator(FieldDefinition field) {
+ field.getADecorator().getExpression().flow() = sanitizingDecorator().getReturn().getAUse()
+ }
+
+ pragma[noinline]
+ private predicate isFieldSanitizedByDecorator(ClassDefinition cls, string name) {
+ isFieldSanitizedByDecorator(cls.getField(name))
+ }
+
+ pragma[noinline]
+ private ClassDefinition getClassReferencedByPropRead(DataFlow::PropRead read) {
+ read.getBase().asExpr().getType().unfold().(ClassType).getClass() = result
+ }
+
+ /**
+ * Holds if the given property read refers to a field that has a sanitizing decorator.
+ *
+ * Only holds when TypeScript types are available.
+ */
+ pragma[noinline]
+ predicate isAccessToSanitizedField(DataFlow::PropRead read) {
+ exists(ClassDefinition class_ |
+ class_ = getClassReferencedByPropRead(read) and
+ isFieldSanitizedByDecorator(class_, read.getPropertyName())
+ )
+ }
+}
diff --git a/javascript/ql/src/semmle/javascript/frameworks/Nest.qll b/javascript/ql/src/semmle/javascript/frameworks/Nest.qll
new file mode 100644
index 00000000000..297897b3541
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/frameworks/Nest.qll
@@ -0,0 +1,443 @@
+/**
+ * Provides classes and predicates for reasoning about [Nest](https://nestjs.com/).
+ */
+
+import javascript
+private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations
+
+/**
+ * Provides classes and predicates for reasoning about [Nest](https://nestjs.com/).
+ */
+module NestJS {
+ /** Gets an API node referring to the `@nestjs/common` module. */
+ private API::Node nestjs() { result = API::moduleImport("@nestjs/common") }
+
+ /**
+ * Gets a data flow node that is applied as a decorator on the given function.
+ *
+ * Note that only methods in a class can have decorators.
+ */
+ private DataFlow::Node getAFunctionDecorator(DataFlow::FunctionNode fun) {
+ exists(MethodDefinition method |
+ fun = method.getInit().flow() and
+ result = method.getADecorator().getExpression().flow()
+ )
+ }
+
+ /**
+ * A method that is declared as a route handler using a decorator, for example:
+ *
+ * ```js
+ * class C {
+ * @Get('posts')
+ * getPosts() { .. }
+ * }
+ * ```
+ */
+ private class NestJSRouteHandler extends HTTP::RouteHandler, DataFlow::FunctionNode {
+ NestJSRouteHandler() {
+ getAFunctionDecorator(this) =
+ nestjs()
+ .getMember(["Get", "Post", "Put", "Delete", "Patch", "Options", "Head", "All"])
+ .getACall()
+ }
+
+ override HTTP::HeaderDefinition getAResponseHeader(string name) { none() }
+
+ /**
+ * Holds if this has the `@Redirect()` decorator.
+ */
+ predicate hasRedirectDecorator() {
+ getAFunctionDecorator(this) = nestjs().getMember("Redirect").getACall()
+ }
+
+ /** Gets a pipe applied to the inputs of this route handler, not including global pipes. */
+ DataFlow::Node getAPipe() {
+ exists(DataFlow::CallNode decorator |
+ decorator = nestjs().getMember("UsePipes").getACall() and
+ result = decorator.getAnArgument()
+ |
+ decorator = getAFunctionDecorator(this)
+ or
+ exists(DataFlow::ClassNode cls |
+ this = cls.getAnInstanceMember() and
+ decorator = cls.getADecorator()
+ )
+ )
+ }
+ }
+
+ /**
+ * A parameter with a decorator that makes it receive a value derived from the incoming request.
+ *
+ * For example, in the following,
+ * ```js
+ * @Get(':foo')
+ * foo(@Param('foo') foo, @Query() query) { ... }
+ * ```
+ * the `foo` and `query` parameters receive (part of) the path and query string, respectively.
+ */
+ private class NestJSRequestInput extends DataFlow::ParameterNode {
+ DataFlow::CallNode decorator;
+ string decoratorName;
+
+ NestJSRequestInput() {
+ decoratorName =
+ ["Query", "Param", "Headers", "Body", "HostParam", "UploadedFile", "UploadedFiles"] and
+ decorator = getADecorator() and
+ decorator = nestjs().getMember(decoratorName).getACall()
+ }
+
+ /** Gets the decorator marking this as a request input. */
+ DataFlow::CallNode getDecorator() { result = decorator }
+
+ /** Gets the route handler on which this parameter appears. */
+ NestJSRouteHandler getNestRouteHandler() { result.getAParameter() = this }
+
+ /** Gets a pipe applied to this parameter, not including global pipes. */
+ DataFlow::Node getAPipe() {
+ result = getNestRouteHandler().getAPipe()
+ or
+ result = decorator.getArgument(1)
+ or
+ decorator.getNumArgument() = 1 and
+ not decorator.getArgument(0).mayHaveStringValue(_) and
+ result = decorator.getArgument(0) // One-argument version can either take a pipe or a property name
+ }
+
+ /** Gets the kind of parameter, for use in `HTTP::RequestInputAccess`. */
+ string getInputKind() {
+ decoratorName = ["Param", "Query"] and result = "parameter"
+ or
+ decoratorName = ["Headers", "HostParam"] and result = "header"
+ or
+ decoratorName = ["Body", "UploadedFile", "UploadedFiles"] and result = "body"
+ }
+
+ /**
+ * Holds if this is sanitized by a sanitizing pipe, for example, a parameter
+ * with the decorator `@Param('x', ParseIntPipe)` is parsed as an integer, and
+ * is thus considered to be sanitized.
+ */
+ predicate isSanitizedByPipe() {
+ hasSanitizingPipe(this, false)
+ or
+ hasSanitizingPipe(this, true) and
+ isSanitizingType(getParameter().getType().unfold())
+ }
+ }
+
+ /** API node entry point for custom implementations of `ValidationPipe` (a common pattern). */
+ private class ValidationNodeEntry extends API::EntryPoint {
+ ValidationNodeEntry() { this = "ValidationNodeEntry" }
+
+ override DataFlow::SourceNode getAUse() {
+ result.(DataFlow::ClassNode).getName() = "ValidationPipe"
+ }
+
+ override DataFlow::Node getARhs() { none() }
+ }
+
+ /** Gets an API node referring to the constructor of `ValidationPipe` */
+ private API::Node validationPipe() {
+ result = nestjs().getMember("ValidationPipe")
+ or
+ result = API::root().getASuccessor(any(ValidationNodeEntry e))
+ }
+
+ /**
+ * Gets a pipe (instance or constructor) which causes its input to be sanitized, and thus not seen as a `RequestInputAccess`.
+ *
+ * If `dependsOnType` is `true`, then the validation depends on the declared type of the input,
+ * and some types may not be enough to be considered sanitized.
+ */
+ private API::Node sanitizingPipe(boolean dependsOnType) {
+ exists(API::Node ctor |
+ dependsOnType = false and
+ ctor = nestjs().getMember(["ParseIntPipe", "ParseBoolPipe", "ParseUUIDPipe"])
+ or
+ dependsOnType = true and
+ ctor = validationPipe()
+ |
+ result = [ctor, ctor.getInstance()]
+ )
+ }
+
+ /**
+ * Holds if `ValidationPipe` is installed as a global pipe by a file in the given folder
+ * or one of its enclosing folders.
+ *
+ * We use folder hierarchy to approximate the scope of globally-installed pipes.
+ */
+ predicate hasGlobalValidationPipe(Folder folder) {
+ exists(DataFlow::CallNode call |
+ call.getCalleeName() = "useGlobalPipes" and
+ call.getArgument(0) = validationPipe().getInstance().getAUse() and
+ folder = call.getFile().getParentContainer()
+ )
+ or
+ exists(API::CallNode decorator |
+ decorator = nestjs().getMember("Module").getACall() and
+ decorator
+ .getParameter(0)
+ .getMember("providers")
+ .getAMember()
+ .getMember("useFactory")
+ .getReturn()
+ .getARhs() = validationPipe().getInstance().getAUse() and
+ folder = decorator.getFile().getParentContainer()
+ )
+ or
+ hasGlobalValidationPipe(folder.getParentContainer())
+ }
+
+ /**
+ * Holds if `param` is affected by a pipe that sanitizes inputs.
+ */
+ private predicate hasSanitizingPipe(NestJSRequestInput param, boolean dependsOnType) {
+ param.getAPipe() = sanitizingPipe(dependsOnType).getAUse()
+ or
+ hasGlobalValidationPipe(param.getFile().getParentContainer()) and
+ dependsOnType = true
+ }
+
+ /**
+ * Holds if a parameter of type `t` is considered sanitized, provided it has been checked by `ValidationPipe`
+ * (which relies on metadata emitted by the TypeScript compiler).
+ */
+ private predicate isSanitizingType(Type t) {
+ t instanceof NumberType
+ or
+ t instanceof BooleanType
+ //
+ // Note: we could consider types with class-validator decorators to be sanitized here, but instead we consider the root
+ // object to be tainted, but omit taint steps for the individual properties names that have sanitizing decorators. See ClassValidator.qll.
+ }
+
+ /**
+ * A user-defined pipe class, for example:
+ * ```js
+ * class MyPipe implements PipeTransform {
+ * transform(value) { return value + '!' }
+ * }
+ * ```
+ * This can be used as a pipe, for example, `@Param('x', MyPipe)` would pipe
+ * the request parameter `x` through the `transform` function before flowing into
+ * the route handler.
+ */
+ private class CustomPipeClass extends DataFlow::ClassNode {
+ CustomPipeClass() {
+ exists(ClassDefinition cls |
+ this = cls.flow() and
+ cls.getASuperInterface().hasQualifiedName("@nestjs/common", "PipeTransform")
+ )
+ }
+
+ DataFlow::FunctionNode getTransformFunction() { result = getInstanceMethod("transform") }
+
+ DataFlow::ParameterNode getInputData() { result = getTransformFunction().getParameter(0) }
+
+ DataFlow::Node getOutputData() { result = getTransformFunction().getReturnNode() }
+
+ NestJSRequestInput getAnAffectedParameter() {
+ [getAnInstanceReference(), getAClassReference()].flowsTo(result.getAPipe())
+ }
+ }
+
+ /**
+ * The input to a custom pipe, seen as a remote flow source.
+ *
+ * The type of remote flow depends on which decorator is applied at the parameter, so
+ * we just classify it as a `RemoteFlowSource`.
+ */
+ private class NestJSCustomPipeInput extends HTTP::RequestInputAccess {
+ CustomPipeClass pipe;
+
+ NestJSCustomPipeInput() {
+ this = pipe.getInputData() and
+ exists(NestJSRequestInput input |
+ input = pipe.getAnAffectedParameter() and
+ not input.isSanitizedByPipe()
+ )
+ }
+
+ override string getKind() {
+ // Use any input kind that the pipe is applied to.
+ result = pipe.getAnAffectedParameter().getInputKind()
+ }
+
+ override HTTP::RouteHandler getRouteHandler() {
+ result = pipe.getAnAffectedParameter().getNestRouteHandler()
+ }
+ }
+
+ /**
+ * A step from the result of a custom pipe, to an affected parameter.
+ */
+ private class CustomPipeStep extends DataFlow::SharedFlowStep {
+ override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
+ exists(CustomPipeClass pipe |
+ pred = pipe.getOutputData() and
+ succ = pipe.getAnAffectedParameter()
+ )
+ }
+ }
+
+ /**
+ * A request input parameter that is not sanitized by a pipe, and therefore treated
+ * as a source of untrusted data.
+ */
+ private class NestJSRequestInputAsRequestInputAccess extends NestJSRequestInput,
+ HTTP::RequestInputAccess {
+ NestJSRequestInputAsRequestInputAccess() {
+ not isSanitizedByPipe() and
+ not this = any(CustomPipeClass cls).getAnAffectedParameter()
+ }
+
+ override HTTP::RouteHandler getRouteHandler() { result = getNestRouteHandler() }
+
+ override string getKind() { result = getInputKind() }
+
+ override predicate isUserControlledObject() {
+ not exists(getAPipe()) and // value is not transformed by a pipe
+ (
+ decorator.getNumArgument() = 0
+ or
+ decoratorName = ["Query", "Body"]
+ )
+ }
+ }
+
+ private class NestJSHeaderAccess extends NestJSRequestInputAsRequestInputAccess,
+ HTTP::RequestHeaderAccess {
+ NestJSHeaderAccess() { decoratorName = "Headers" and decorator.getNumArgument() > 0 }
+
+ override string getAHeaderName() {
+ result = decorator.getArgument(0).getStringValue().toLowerCase()
+ }
+ }
+
+ /**
+ * A return value from a route handler, seen as an argument to `res.send()`.
+ *
+ * For example,
+ * ```js
+ * @Get()
+ * foo() {
+ * return 'Hello';
+ * }
+ * ```
+ * writes `Hello` to the response.
+ */
+ private class ReturnValueAsResponseSend extends HTTP::ResponseSendArgument {
+ NestJSRouteHandler handler;
+
+ ReturnValueAsResponseSend() {
+ not handler.hasRedirectDecorator() and
+ this = handler.getAReturn().asExpr()
+ }
+
+ override HTTP::RouteHandler getRouteHandler() { result = handler }
+ }
+
+ /**
+ * A return value from a redirecting route handler, seen as a sink for server-side redirect.
+ *
+ * For example,
+ * ```js
+ * @Get()
+ * @Redirect
+ * foo() {
+ * return { url: 'https://example.com' }
+ * }
+ * ```
+ * redirects to `https://example.com`.
+ */
+ private class ReturnValueAsRedirection extends ServerSideUrlRedirect::Sink {
+ NestJSRouteHandler handler;
+
+ ReturnValueAsRedirection() {
+ handler.hasRedirectDecorator() and
+ this = handler.getAReturn().getALocalSource().getAPropertyWrite("url").getRhs()
+ }
+ }
+
+ /**
+ * A parameter decorator created using `createParamDecorator`.
+ */
+ private class CustomParameterDecorator extends API::CallNode {
+ CustomParameterDecorator() { this = nestjs().getMember("createParamDecorator").getACall() }
+
+ /** Gets the `context` parameter. */
+ API::Node getExecutionContext() { result = getParameter(0).getParameter(1) }
+
+ /** Gets a parameter with this decorator applied. */
+ DataFlow::ParameterNode getADecoratedParameter() {
+ result.getADecorator() = getReturn().getReturn().getAUse()
+ }
+
+ /** Gets a value returned by the decorator's callback, which becomes the value of the decorated parameter. */
+ DataFlow::Node getResult() { result = getParameter(0).getReturn().getARhs() }
+ }
+
+ /**
+ * A flow step from a custom parameter decorator to a decorated parameter.
+ */
+ private class CustomParameterFlowStep extends DataFlow::SharedFlowStep {
+ override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
+ exists(CustomParameterDecorator dec |
+ pred = dec.getResult() and
+ succ = dec.getADecoratedParameter()
+ )
+ }
+ }
+
+ private API::Node executionContext() {
+ result = API::Node::ofType("@nestjs/common", "ExecutionContext")
+ or
+ result = any(CustomParameterDecorator d).getExecutionContext()
+ }
+
+ /**
+ * A source of `express` request objects, based on the `@Req()` decorator,
+ * or the context object in a custom decorator.
+ */
+ private class ExpressRequestSource extends Express::RequestSource {
+ ExpressRequestSource() {
+ this.(DataFlow::ParameterNode).getADecorator() =
+ nestjs().getMember(["Req", "Request"]).getReturn().getAnImmediateUse()
+ or
+ this =
+ executionContext()
+ .getMember("switchToHttp")
+ .getReturn()
+ .getMember("getRequest")
+ .getReturn()
+ .getAnImmediateUse()
+ }
+
+ /**
+ * Gets the route handler that handles this request.
+ */
+ override HTTP::RouteHandler getRouteHandler() {
+ result.(DataFlow::FunctionNode).getAParameter() = this
+ }
+ }
+
+ /**
+ * A source of `express` response objects, based on the `@Res()` decorator.
+ */
+ private class ExpressResponseSource extends Express::ResponseSource {
+ ExpressResponseSource() {
+ this.(DataFlow::ParameterNode).getADecorator() =
+ nestjs().getMember(["Res", "Response"]).getReturn().getAnImmediateUse()
+ }
+
+ /**
+ * Gets the route handler that handles this request.
+ */
+ override HTTP::RouteHandler getRouteHandler() {
+ result.(DataFlow::FunctionNode).getAParameter() = this
+ }
+ }
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/Consistency.expected b/javascript/ql/test/library-tests/frameworks/Nest/Consistency.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/Consistency.ql b/javascript/ql/test/library-tests/frameworks/Nest/Consistency.ql
new file mode 100644
index 00000000000..787d0a5fdc4
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/Consistency.ql
@@ -0,0 +1,3 @@
+import testUtilities.ConsistencyChecking
+import semmle.javascript.security.dataflow.ReflectedXss
+import semmle.javascript.security.dataflow.ServerSideUrlRedirect
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/global/app.ts b/javascript/ql/test/library-tests/frameworks/Nest/global/app.ts
new file mode 100644
index 00000000000..132f2162a9f
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/global/app.ts
@@ -0,0 +1,10 @@
+import { NestFactory } from '@nestjs/core';
+import { ValidationPipe } from '@nestjs/common';
+import { AppModule } from './app.module';
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+ app.useGlobalPipes(new ValidationPipe());
+ await app.listen(3000);
+}
+bootstrap();
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/global/validation.ts b/javascript/ql/test/library-tests/frameworks/Nest/global/validation.ts
new file mode 100644
index 00000000000..4bf67eff4cb
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/global/validation.ts
@@ -0,0 +1,15 @@
+import { Get, Query } from '@nestjs/common';
+import { IsIn } from 'class-validator';
+
+export class Controller {
+ @Get()
+ route1(@Query('x') validatedObj: Struct, @Query('y') unvalidated: string) {
+ if (Math.random()) return unvalidated; // NOT OK
+ return validatedObj.key; // OK
+ }
+}
+
+class Struct {
+ @IsIn(['foo', 'bar'])
+ key: string;
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/local/customDecorator.ts b/javascript/ql/test/library-tests/frameworks/Nest/local/customDecorator.ts
new file mode 100644
index 00000000000..032d7032bc0
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/local/customDecorator.ts
@@ -0,0 +1,26 @@
+import { Get, createParamDecorator, ExecutionContext } from '@nestjs/common';
+
+export const SneakyQueryParam = createParamDecorator(
+ (data: unknown, ctx: ExecutionContext) => {
+ const request = ctx.switchToHttp().getRequest();
+ return request.query.sneakyQueryParam;
+ },
+);
+
+export const SafeParam = createParamDecorator(
+ (data: unknown, ctx: ExecutionContext) => {
+ return 'Safe';
+ },
+);
+
+export class Controller {
+ @Get()
+ sneaky(@SneakyQueryParam() value) {
+ return value; // NOT OK
+ }
+
+ @Get()
+ safe(@SafeParam() value) {
+ return value; // OK
+ }
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/local/customPipe.ts b/javascript/ql/test/library-tests/frameworks/Nest/local/customPipe.ts
new file mode 100644
index 00000000000..58f6084ab0b
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/local/customPipe.ts
@@ -0,0 +1,50 @@
+import { Get, Injectable, PipeTransform, Query, UsePipes } from '@nestjs/common';
+
+@Injectable()
+export class CustomSanitizingPipe implements PipeTransform {
+ transform(value: string): number | undefined {
+ if (value == null) return undefined;
+ return Number(value);
+ }
+}
+
+@Injectable()
+export class CustomPropagatingPipe implements PipeTransform {
+ transform(value: string): string {
+ return value.toUpperCase() + '!';
+ }
+}
+
+export class Controller {
+ @Get()
+ sanitizingPipe1(@Query('x', CustomSanitizingPipe) sanitized: number): string {
+ return '' + sanitized; // OK
+ }
+
+ @Get()
+ sanitizingPipe2(@Query('x', new CustomSanitizingPipe()) sanitized: number): string {
+ return '' + sanitized; // OK
+ }
+
+ @Get()
+ @UsePipes(CustomSanitizingPipe)
+ sanitizingPipe3(@Query('x') sanitized: number): string {
+ return '' + sanitized; // OK
+ }
+
+ @Get()
+ propagatingPipe1(@Query('x', CustomPropagatingPipe) unsanitized: string): string {
+ return '' + unsanitized; // NOT OK
+ }
+
+ @Get()
+ propagatingPipe2(@Query('x', new CustomPropagatingPipe()) unsanitized: string): string {
+ return '' + unsanitized; // NOT OK
+ }
+
+ @Get()
+ @UsePipes(CustomPropagatingPipe)
+ propagatingPipe3(@Query('x') unsanitized: string): string {
+ return '' + unsanitized; // NOT OK
+ }
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/local/routes.ts b/javascript/ql/test/library-tests/frameworks/Nest/local/routes.ts
new file mode 100644
index 00000000000..b94c3942318
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/local/routes.ts
@@ -0,0 +1,74 @@
+import { Get, Post, All, Query, Param, Body, Redirect, Req, Res, UploadedFile, UploadedFiles } from '@nestjs/common';
+import { SneakyQueryParam } from './customDecorator';
+
+export class TestController {
+ @Get('foo')
+ getFoo() {
+ return 'foo';
+ }
+
+ @Post('foo')
+ postFoo() {
+ return 'foo';
+ }
+
+ @Get()
+ getRoot() {
+ return 'foo';
+ }
+
+ @All('bar')
+ bar() {
+ return 'bar';
+ }
+
+ @Get('requestInputs/:x')
+ requestInputs(
+ @Param('x') x,
+ @Query() queryObj,
+ @Query('name') name,
+ @Req() req
+ ) {
+ if (Math.random()) return x; // NOT OK
+ if (Math.random()) return queryObj; // NOT OK
+ if (Math.random()) return name; // NOT OK
+ if (Math.random()) return req.query.abc; // NOT OK
+ return;
+ }
+
+ @Post('post')
+ post(@Body() body) {
+ return body.x; // NOT OK
+ }
+
+ @Get('redir')
+ @Redirect('https://example.com')
+ redir() {
+ return {
+ url: '//other.example.com' // OK
+ };
+ }
+
+ @Get('redir')
+ @Redirect('https://example.com')
+ redir2(@Query('redirect') target) {
+ return {
+ url: target // NOT OK
+ };
+ }
+
+ @Get()
+ explicitSend(@Req() req, @Res() res) {
+ res.send(req.query.x) // NOT OK
+ }
+
+ @Post()
+ upload(@UploadedFile() file) {
+ return file.originalname; // NOT OK
+ }
+
+ @Post()
+ uploadMany(@UploadedFiles() files) {
+ return files[0].originalname; // NOT OK
+ }
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/local/validation.ts b/javascript/ql/test/library-tests/frameworks/Nest/local/validation.ts
new file mode 100644
index 00000000000..d9771c195e1
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/local/validation.ts
@@ -0,0 +1,51 @@
+import { Get, Query, UsePipes, ValidationPipe } from '@nestjs/common';
+import { IsIn } from 'class-validator';
+
+export class Controller {
+ @Get()
+ route1(@Query('x', new ValidationPipe()) validatedObj: Struct) {
+ return validatedObj.key; // OK
+ }
+
+ @Get()
+ route2(@Query('x', ValidationPipe) validatedObj: Struct) {
+ return validatedObj.key; // OK
+ }
+
+ @Get()
+ @UsePipes(new ValidationPipe())
+ route3(@Query('x') validatedObj: Struct, @Query('y') unvalidated: string) {
+ if (Math.random()) return validatedObj.key; // OK
+ return unvalidated; // NOT OK
+ }
+
+ @Get()
+ @UsePipes(ValidationPipe)
+ route4(@Query('x') validatedObj: Struct, @Query('y') unvalidated: string) {
+ if (Math.random()) return validatedObj.key; // OK
+ return unvalidated; // NOT OK
+ }
+}
+
+@UsePipes(new ValidationPipe())
+export class Controller2 {
+ @Get()
+ route5(@Query('x') validatedObj: Struct, @Query('y') unvalidated: string) {
+ if (Math.random()) return validatedObj.key; // OK
+ return unvalidated; // NOT OK
+ }
+}
+
+@UsePipes(ValidationPipe)
+export class Controller3 {
+ @Get()
+ route6(@Query('x') validatedObj: Struct, @Query('y') unvalidated: string) {
+ if (Math.random()) return validatedObj.key; // OK
+ return unvalidated; // NOT OK
+ }
+}
+
+class Struct {
+ @IsIn(['foo', 'bar'])
+ key: string;
+}
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/test.expected b/javascript/ql/test/library-tests/frameworks/Nest/test.expected
new file mode 100644
index 00000000000..9de016189ba
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/test.expected
@@ -0,0 +1,94 @@
+routeHandler
+| global/validation.ts:6:3:9:3 | route1( ... OK\\n } |
+| local/customDecorator.ts:18:3:20:3 | sneaky( ... OK\\n } |
+| local/customDecorator.ts:23:3:25:3 | safe(@S ... OK\\n } |
+| local/customPipe.ts:20:5:22:5 | sanitiz ... K\\n } |
+| local/customPipe.ts:25:5:27:5 | sanitiz ... K\\n } |
+| local/customPipe.ts:31:5:33:5 | sanitiz ... K\\n } |
+| local/customPipe.ts:36:5:38:5 | propaga ... K\\n } |
+| local/customPipe.ts:41:5:43:5 | propaga ... K\\n } |
+| local/customPipe.ts:47:5:49:5 | propaga ... K\\n } |
+| local/routes.ts:6:3:8:3 | getFoo( ... o';\\n } |
+| local/routes.ts:11:3:13:3 | postFoo ... o';\\n } |
+| local/routes.ts:16:3:18:3 | getRoot ... o';\\n } |
+| local/routes.ts:21:3:23:3 | bar() { ... r';\\n } |
+| local/routes.ts:26:3:37:3 | request ... rn;\\n } |
+| local/routes.ts:40:3:42:3 | post(@B ... OK\\n } |
+| local/routes.ts:46:3:50:3 | redir() ... };\\n } |
+| local/routes.ts:54:3:58:3 | redir2( ... };\\n } |
+| local/routes.ts:61:3:63:3 | explici ... OK\\n } |
+| local/routes.ts:66:3:68:3 | upload( ... OK\\n } |
+| local/routes.ts:71:3:73:3 | uploadM ... OK\\n } |
+| local/validation.ts:6:3:8:3 | route1( ... OK\\n } |
+| local/validation.ts:11:3:13:3 | route2( ... OK\\n } |
+| local/validation.ts:17:3:20:3 | route3( ... OK\\n } |
+| local/validation.ts:24:3:27:3 | route4( ... OK\\n } |
+| local/validation.ts:33:3:36:3 | route5( ... OK\\n } |
+| local/validation.ts:42:3:45:3 | route6( ... OK\\n } |
+requestSource
+| local/customDecorator.ts:5:21:5:51 | ctx.swi ... quest() |
+| local/routes.ts:30:12:30:14 | req |
+| local/routes.ts:61:23:61:25 | req |
+responseSource
+| local/routes.ts:61:35:61:37 | res |
+requestInputAccess
+| body | local/routes.ts:40:16:40:19 | body |
+| body | local/routes.ts:66:26:66:29 | file |
+| body | local/routes.ts:71:31:71:35 | files |
+| parameter | global/validation.ts:6:22:6:33 | validatedObj |
+| parameter | global/validation.ts:6:56:6:66 | unvalidated |
+| parameter | local/customDecorator.ts:6:12:6:41 | request ... ryParam |
+| parameter | local/customPipe.ts:5:15:5:19 | value |
+| parameter | local/customPipe.ts:13:15:13:19 | value |
+| parameter | local/routes.ts:27:17:27:17 | x |
+| parameter | local/routes.ts:28:14:28:21 | queryObj |
+| parameter | local/routes.ts:29:20:29:23 | name |
+| parameter | local/routes.ts:35:31:35:43 | req.query.abc |
+| parameter | local/routes.ts:54:29:54:34 | target |
+| parameter | local/routes.ts:62:14:62:24 | req.query.x |
+| parameter | local/validation.ts:6:44:6:55 | validatedObj |
+| parameter | local/validation.ts:11:38:11:49 | validatedObj |
+| parameter | local/validation.ts:17:22:17:33 | validatedObj |
+| parameter | local/validation.ts:17:56:17:66 | unvalidated |
+| parameter | local/validation.ts:24:22:24:33 | validatedObj |
+| parameter | local/validation.ts:24:56:24:66 | unvalidated |
+| parameter | local/validation.ts:33:22:33:33 | validatedObj |
+| parameter | local/validation.ts:33:56:33:66 | unvalidated |
+| parameter | local/validation.ts:42:22:42:33 | validatedObj |
+| parameter | local/validation.ts:42:56:42:66 | unvalidated |
+responseSendArgument
+| global/validation.ts:7:31:7:41 | unvalidated |
+| global/validation.ts:8:12:8:27 | validatedObj.key |
+| local/customDecorator.ts:19:12:19:16 | value |
+| local/customDecorator.ts:24:12:24:16 | value |
+| local/customPipe.ts:21:16:21:29 | '' + sanitized |
+| local/customPipe.ts:26:16:26:29 | '' + sanitized |
+| local/customPipe.ts:32:16:32:29 | '' + sanitized |
+| local/customPipe.ts:37:16:37:31 | '' + unsanitized |
+| local/customPipe.ts:42:16:42:31 | '' + unsanitized |
+| local/customPipe.ts:48:16:48:31 | '' + unsanitized |
+| local/routes.ts:7:12:7:16 | 'foo' |
+| local/routes.ts:12:12:12:16 | 'foo' |
+| local/routes.ts:17:12:17:16 | 'foo' |
+| local/routes.ts:22:12:22:16 | 'bar' |
+| local/routes.ts:32:31:32:31 | x |
+| local/routes.ts:33:31:33:38 | queryObj |
+| local/routes.ts:34:31:34:34 | name |
+| local/routes.ts:35:31:35:43 | req.query.abc |
+| local/routes.ts:41:12:41:17 | body.x |
+| local/routes.ts:62:14:62:24 | req.query.x |
+| local/routes.ts:67:12:67:28 | file.originalname |
+| local/routes.ts:72:12:72:32 | files[0 ... nalname |
+| local/validation.ts:7:12:7:27 | validatedObj.key |
+| local/validation.ts:12:12:12:27 | validatedObj.key |
+| local/validation.ts:18:31:18:46 | validatedObj.key |
+| local/validation.ts:19:12:19:22 | unvalidated |
+| local/validation.ts:25:31:25:46 | validatedObj.key |
+| local/validation.ts:26:12:26:22 | unvalidated |
+| local/validation.ts:34:31:34:46 | validatedObj.key |
+| local/validation.ts:35:12:35:22 | unvalidated |
+| local/validation.ts:43:31:43:46 | validatedObj.key |
+| local/validation.ts:44:12:44:22 | unvalidated |
+redirectSink
+| local/routes.ts:48:12:48:32 | '//othe ... le.com' |
+| local/routes.ts:56:12:56:17 | target |
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/test.ql b/javascript/ql/test/library-tests/frameworks/Nest/test.ql
new file mode 100644
index 00000000000..120727d2548
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/test.ql
@@ -0,0 +1,19 @@
+import javascript
+private import semmle.javascript.security.dataflow.ServerSideUrlRedirectCustomizations
+
+query HTTP::RouteHandler routeHandler() { any() }
+
+query HTTP::Servers::RequestSource requestSource() { any() }
+
+query HTTP::Servers::ResponseSource responseSource() { any() }
+
+query RemoteFlowSource requestInputAccess(string kind) {
+ kind = result.(HTTP::RequestInputAccess).getKind()
+ or
+ not result instanceof HTTP::RequestInputAccess and
+ kind = "RemoteFlowSource"
+}
+
+query HTTP::ResponseSendArgument responseSendArgument() { any() }
+
+query ServerSideUrlRedirect::Sink redirectSink() { any() }
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/tsconfig.json b/javascript/ql/test/library-tests/frameworks/Nest/tsconfig.json
new file mode 100644
index 00000000000..c5df21cd7d4
--- /dev/null
+++ b/javascript/ql/test/library-tests/frameworks/Nest/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "compilerOptions": {
+ "experimentalDecorators": true
+ },
+ "include": ["."]
+}
From d0b8b323459760231ede07df240acc29aed87fbb Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Thu, 15 Apr 2021 14:33:05 +0100
Subject: [PATCH 087/550] JS: Add change notes
---
javascript/change-notes/2021-04-15-fs-promises.md | 3 +++
javascript/change-notes/2021-04-15-nestjs.md | 3 +++
2 files changed, 6 insertions(+)
create mode 100644 javascript/change-notes/2021-04-15-fs-promises.md
create mode 100644 javascript/change-notes/2021-04-15-nestjs.md
diff --git a/javascript/change-notes/2021-04-15-fs-promises.md b/javascript/change-notes/2021-04-15-fs-promises.md
new file mode 100644
index 00000000000..f410f00edb1
--- /dev/null
+++ b/javascript/change-notes/2021-04-15-fs-promises.md
@@ -0,0 +1,3 @@
+lgtm,codescanning
+* Support for `fs.promises` has been added, leading to more results for security queries
+ related to file system access.
diff --git a/javascript/change-notes/2021-04-15-nestjs.md b/javascript/change-notes/2021-04-15-nestjs.md
new file mode 100644
index 00000000000..5eaa0e5af69
--- /dev/null
+++ b/javascript/change-notes/2021-04-15-nestjs.md
@@ -0,0 +1,3 @@
+lgtm,codescanning
+* Support for Nest.js has been added. The security queries now recognize sources and sinks
+ specific to the Nest.js framework.
From 4f53a1ab409bce25bc0ac52ef60582f2d884f83f Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Wed, 21 Apr 2021 14:48:52 +0100
Subject: [PATCH 088/550] JS: Cache ClassNode::Range
---
.../ql/src/semmle/javascript/dataflow/Nodes.qll | 11 +++++++++++
.../src/semmle/javascript/internal/CachedStages.qll | 2 ++
2 files changed, 13 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
index 5a110f44ff8..19fe93da259 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
@@ -1081,35 +1081,42 @@ module ClassNode {
* Subclass this to introduce new kinds of class nodes. If you want to refine
* the definition of existing class nodes, subclass `DataFlow::ClassNode` instead.
*/
+ cached
abstract class Range extends DataFlow::SourceNode {
/**
* Gets the name of the class, if it has one.
*/
+ cached
abstract string getName();
/**
* Gets a description of the class.
*/
+ cached
abstract string describe();
/**
* Gets the constructor function of this class.
*/
+ cached
abstract FunctionNode getConstructor();
/**
* Gets the instance member with the given name and kind.
*/
+ cached
abstract FunctionNode getInstanceMember(string name, MemberKind kind);
/**
* Gets an instance member with the given kind.
*/
+ cached
abstract FunctionNode getAnInstanceMember(MemberKind kind);
/**
* Gets the static method of this class with the given name.
*/
+ cached
abstract FunctionNode getStaticMethod(string name);
/**
@@ -1117,20 +1124,24 @@ module ClassNode {
*
* The constructor is not considered a static method.
*/
+ cached
abstract FunctionNode getAStaticMethod();
/**
* Gets a dataflow node representing a class to be used as the super-class
* of this node.
*/
+ cached
abstract DataFlow::Node getASuperClassNode();
/**
* Gets the type annotation for the field `fieldName`, if any.
*/
+ cached
TypeAnnotation getFieldTypeAnnotation(string fieldName) { none() }
/** Gets a decorator applied to this class. */
+ cached
DataFlow::Node getADecorator() { none() }
}
diff --git a/javascript/ql/src/semmle/javascript/internal/CachedStages.qll b/javascript/ql/src/semmle/javascript/internal/CachedStages.qll
index 6980a6eef7f..80d0930cbed 100644
--- a/javascript/ql/src/semmle/javascript/internal/CachedStages.qll
+++ b/javascript/ql/src/semmle/javascript/internal/CachedStages.qll
@@ -135,6 +135,8 @@ module Stages {
exists(any(AccessPath a).getAnInstanceIn(_))
or
exists(any(DataFlow::PropRef ref).getBase())
+ or
+ exists(any(DataFlow::ClassNode cls))
}
}
From 71e3041370735b3220853a666722b06a13b58df7 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Fri, 23 Apr 2021 13:15:13 +0100
Subject: [PATCH 089/550] JS: Fewer spurious reflected xss sinks
---
.../src/semmle/javascript/frameworks/Nest.qll | 26 +++++++++++++++++--
.../frameworks/Nest/test.expected | 4 ---
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/Nest.qll b/javascript/ql/src/semmle/javascript/frameworks/Nest.qll
index 297897b3541..d216fac1712 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/Nest.qll
@@ -51,6 +51,15 @@ module NestJS {
getAFunctionDecorator(this) = nestjs().getMember("Redirect").getACall()
}
+ /**
+ * Holds if the return value is sent back in the response.
+ */
+ predicate isReturnValueReflected() {
+ getAFunctionDecorator(this) = nestjs().getMember(["Get", "Post"]).getACall() and
+ not hasRedirectDecorator() and
+ not getAFunctionDecorator(this) = nestjs().getMember("Render").getACall()
+ }
+
/** Gets a pipe applied to the inputs of this route handler, not including global pipes. */
DataFlow::Node getAPipe() {
exists(DataFlow::CallNode decorator |
@@ -317,6 +326,14 @@ module NestJS {
}
}
+ private predicate isStringType(Type type) {
+ type instanceof StringType
+ or
+ type instanceof AnyType
+ or
+ isStringType(type.(PromiseType).getElementType().unfold())
+ }
+
/**
* A return value from a route handler, seen as an argument to `res.send()`.
*
@@ -333,8 +350,13 @@ module NestJS {
NestJSRouteHandler handler;
ReturnValueAsResponseSend() {
- not handler.hasRedirectDecorator() and
- this = handler.getAReturn().asExpr()
+ handler.isReturnValueReflected() and
+ this = handler.getAReturn().asExpr() and
+ // Only returned strings are sinks
+ not exists(Type type |
+ type = getType() and
+ not isStringType(type.unfold())
+ )
}
override HTTP::RouteHandler getRouteHandler() { result = handler }
diff --git a/javascript/ql/test/library-tests/frameworks/Nest/test.expected b/javascript/ql/test/library-tests/frameworks/Nest/test.expected
index 9de016189ba..c659295f552 100644
--- a/javascript/ql/test/library-tests/frameworks/Nest/test.expected
+++ b/javascript/ql/test/library-tests/frameworks/Nest/test.expected
@@ -67,10 +67,6 @@ responseSendArgument
| local/customPipe.ts:37:16:37:31 | '' + unsanitized |
| local/customPipe.ts:42:16:42:31 | '' + unsanitized |
| local/customPipe.ts:48:16:48:31 | '' + unsanitized |
-| local/routes.ts:7:12:7:16 | 'foo' |
-| local/routes.ts:12:12:12:16 | 'foo' |
-| local/routes.ts:17:12:17:16 | 'foo' |
-| local/routes.ts:22:12:22:16 | 'bar' |
| local/routes.ts:32:31:32:31 | x |
| local/routes.ts:33:31:33:38 | queryObj |
| local/routes.ts:34:31:34:34 | name |
From 0da0670a79750f40f03c3fbbad78210af655b342 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Fri, 23 Apr 2021 11:04:19 +0100
Subject: [PATCH 090/550] JS: Add Nest.js to list of supported framworks
---
docs/codeql/support/reusables/frameworks.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/codeql/support/reusables/frameworks.rst b/docs/codeql/support/reusables/frameworks.rst
index 22569cbdcc6..5f88e3c907d 100644
--- a/docs/codeql/support/reusables/frameworks.rst
+++ b/docs/codeql/support/reusables/frameworks.rst
@@ -128,6 +128,7 @@ JavaScript and TypeScript built-in support
mssql, Database
mysql, Database
node, Runtime environment
+ nest.js, Server
postgres, Database
ramda, Utility library
react, HTML framework
From f2b2300da90f2ff9680f8934985784b968ed7642 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 25 Apr 2021 22:23:31 +0300
Subject: [PATCH 091/550] Add files via upload
---
.../Security/CWE/CWE-415/DoubleFree.c | 13 +++++
.../Security/CWE/CWE-415/DoubleFree.qhelp | 26 ++++++++++
.../Security/CWE/CWE-415/DoubleFree.ql | 51 +++++++++++++++++++
3 files changed, 90 insertions(+)
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.c
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.qhelp
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.c b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.c
new file mode 100644
index 00000000000..978ca445215
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.c
@@ -0,0 +1,13 @@
+...
+ buf = malloc(intSize);
+...
+ free(buf);
+ buf = NULL; // GOOD
+...
+
+...
+ buf = malloc(intSize);
+...
+ free(buf);
+ if(buf) free(buf); // BAD: the cleanup function does not zero out the pointer
+...
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.qhelp
new file mode 100644
index 00000000000..f30d2f2c48b
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.qhelp
@@ -0,0 +1,26 @@
+
+
+
+Double freeing of a previously allocated resource can lead to various vulnerabilities in the program. Requires the attention of developers.
+
+
+
+We recommend that you exclude situations of possible double release.
+
+
+
+The following example demonstrates an erroneous and corrected use of freeing a pointer.
+
+
+
+
+
+
+ CERT C Coding Standard:
+ MEM30-C. Do not access freed memory.
+
+
+
+
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
new file mode 100644
index 00000000000..199dc18bee7
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
@@ -0,0 +1,51 @@
+/**
+ * @name Errors When Double Free
+ * @description Double freeing of a previously allocated resource can lead to various vulnerabilities in the program
+ * and requires the attention of the developer.
+ * @kind problem
+ * @id cpp/errors-when-double-free
+ * @problem.severity warning
+ * @precision medium
+ * @tags security
+ * external/cwe/cwe-415
+ */
+
+import cpp
+
+/**
+ * The function allows `getASuccessor` to be called recursively.
+ * This provides a stop in situations of possible influence on the pointer.
+ */
+ControlFlowNode recursASuccessor(FunctionCall fc, LocalScopeVariable v) {
+ result = fc
+ or
+ exists(ControlFlowNode mid |
+ mid = recursASuccessor(fc, v) and
+ result = mid.getASuccessor() and
+ not result = v.getAnAssignedValue() and
+ not result.(AddressOfExpr).getOperand() = v.getAnAccess() and
+ not (
+ not result instanceof DeallocationExpr and
+ result.(FunctionCall).getAnArgument().(VariableAccess).getTarget() = v
+ ) and
+ (
+ fc.getTarget().hasGlobalOrStdName("realloc") and
+ (
+ not fc.getParent*() instanceof IfStmt and
+ not result instanceof IfStmt
+ )
+ or
+ not fc.getTarget().hasGlobalOrStdName("realloc")
+ )
+ )
+}
+
+from FunctionCall fc
+where
+ exists(FunctionCall fc2, LocalScopeVariable v |
+ freeCall(fc, v.getAnAccess()) and
+ freeCall(fc2, v.getAnAccess()) and
+ fc != fc2 and
+ recursASuccessor(fc, v) = fc2
+ )
+select fc.getArgument(0), "This pointer may be cleared again later."
From c1d125b3786d5d0afa5071a9165e5ba7235bc457 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 25 Apr 2021 22:25:17 +0300
Subject: [PATCH 092/550] Add files via upload
---
.../CWE-415/semmle/tests/DoubleFree.expected | 2 ++
.../CWE/CWE-415/semmle/tests/DoubleFree.qlref | 1 +
.../Security/CWE/CWE-415/semmle/tests/test.c | 21 +++++++++++++++++++
3 files changed, 24 insertions(+)
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.qlref
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
new file mode 100644
index 00000000000..669c65cba2a
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
@@ -0,0 +1,2 @@
+| test.c:9:8:9:10 | buf | This pointer may be cleared again later. |
+| test.c:19:26:19:29 | buf1 | This pointer may be cleared again later. |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.qlref
new file mode 100644
index 00000000000..242beb593f8
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-415/DoubleFree.ql
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
new file mode 100644
index 00000000000..1ebf3546480
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
@@ -0,0 +1,21 @@
+typedef unsigned long size_t;
+void *malloc(size_t size);
+void free(void *ptr);
+
+void workFunction_0(char *s) {
+ int intSize = 10;
+ char *buf;
+ buf = (char *) malloc(intSize);
+ free(buf); // BAD
+ if(buf) free(buf);
+}
+void workFunction_1(char *s) {
+ int intSize = 10;
+ char *buf;
+ char *buf1;
+ buf = (char *) malloc(intSize);
+ buf1 = (char *) realloc(buf,intSize*2);
+ if(buf) free(buf); // GOOD
+ buf = (char *) realloc(buf1,intSize*4); // BAD
+ free(buf1);
+}
From 50c63a88c3036b7ffddd579fe5454fe3ad72cf2f Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 25 Apr 2021 22:34:41 +0300
Subject: [PATCH 093/550] Add files via upload
---
...tionOfVariableWithUnnecessarilyWideScope.c | 14 +++++
...OfVariableWithUnnecessarilyWideScope.qhelp | 26 ++++++++
...ionOfVariableWithUnnecessarilyWideScope.ql | 62 +++++++++++++++++++
3 files changed, 102 insertions(+)
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
create mode 100644 cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
new file mode 100644
index 00000000000..b09971b5328
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
@@ -0,0 +1,14 @@
+while(intIndex > 2)
+{
+ ...
+ intIndex--;
+ ...
+} // GOOD: coreten cycle
+...
+while(intIndex > 2)
+{
+ ...
+ int intIndex;
+ intIndex--;
+ ...
+} // BAD: the variable used in the condition does not change.
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
new file mode 100644
index 00000000000..d84f47f5453
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
@@ -0,0 +1,26 @@
+
+
+
+Using variables with the same name is dangerous. However, such a situation inside the while loop can lead to a violation of the accessibility of the program. Requires the attention of developers.
+
+
+
+We recommend not to use local variables inside a loop if their names are the same as the variables in the condition of this loop.
+
+
+
+The following example demonstrates an erroneous and corrected use of a local variable within a loop.
+
+
+
+
+
+
+ CERT C Coding Standard:
+ DCL01-C. Do not reuse variable names in subscopes.
+
+
+
+
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
new file mode 100644
index 00000000000..a253a5e0599
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
@@ -0,0 +1,62 @@
+/**
+ * @name Errors When Using Variable Declaration Inside Loop
+ * @description Using variables with the same name is dangerous.
+ * However, such a situation inside the while loop can lead to a violation of the accessibility of the program.
+ * Requires the attention of developers.
+ * @kind problem
+ * @id cpp/errors-when-using-variable-declaration-inside-loop
+ * @problem.severity warning
+ * @precision medium
+ * @tags correctness
+ * security
+ * external/cwe/cwe-1126
+ */
+
+import cpp
+
+/**
+ * Errors when using a variable declaration inside a loop.
+ */
+class DangerousWhileLoop extends WhileStmt {
+ Expr exp;
+ Declaration dl;
+
+ DangerousWhileLoop() {
+ this = dl.getParentScope().(BlockStmt).getParent*() and
+ exp = this.getCondition().getAChild*() and
+ not exp instanceof PointerFieldAccess and
+ not exp instanceof ValueFieldAccess and
+ exp.toString() = dl.getName() and
+ not exp.getParent*() instanceof CrementOperation and
+ not exp.getParent*() instanceof Assignment and
+ not exp.getParent*() instanceof FunctionCall
+ }
+
+ Declaration getDeclaration() { result = dl }
+
+ /** Holds when there are changes to the variables involved in the condition. */
+ predicate isUseThisVariable() {
+ exists(Variable v |
+ this.getCondition().getAChild*().(VariableAccess).getTarget() = v and
+ (
+ exists(Assignment aexp |
+ aexp = this.getStmt().getAChild*() and
+ (
+ aexp.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v
+ or
+ aexp.getLValue().(VariableAccess).getTarget() = v
+ )
+ )
+ or
+ exists(CrementOperation crm |
+ crm = this.getStmt().getAChild*() and
+ crm.getOperand().(VariableAccess).getTarget() = v
+ )
+ )
+ )
+ }
+}
+
+from DangerousWhileLoop lp
+where not lp.isUseThisVariable()
+select lp.getDeclaration(), "A variable with this name is used in the loop condition."
From 98f7f70814efa3dae55beb0fd1cb9f4e095d776e Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 25 Apr 2021 22:35:40 +0300
Subject: [PATCH 094/550] Add files via upload
---
...nOfVariableWithUnnecessarilyWideScope.expected | 1 +
...tionOfVariableWithUnnecessarilyWideScope.qlref | 1 +
.../Security/CWE/CWE-1126/semmle/tests/test.c | 15 +++++++++++++++
3 files changed, 17 insertions(+)
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.expected
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.qlref
create mode 100644 cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/test.c
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.expected
new file mode 100644
index 00000000000..7b540a33384
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.expected
@@ -0,0 +1 @@
+| test.c:12:9:12:16 | intIndex | A variable with this name is used in the loop condition. |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.qlref
new file mode 100644
index 00000000000..6da5822f7f0
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/DeclarationOfVariableWithUnnecessarilyWideScope.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/test.c
new file mode 100644
index 00000000000..090bed34d45
--- /dev/null
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-1126/semmle/tests/test.c
@@ -0,0 +1,15 @@
+void workFunction_0(char *s) {
+ int intIndex = 10;
+ char buf[80];
+ while(intIndex > 2) // GOOD
+ {
+ buf[intIndex] = 1;
+ intIndex--;
+ }
+ while(intIndex > 2)
+ {
+ buf[intIndex] = 1;
+ int intIndex; // BAD
+ intIndex--;
+ }
+}
From 3d891f0b391f3623c1baf5fc1ced7b8982e259b2 Mon Sep 17 00:00:00 2001
From: p0wn4j
Date: Wed, 24 Mar 2021 00:08:39 +0400
Subject: [PATCH 095/550] [Java] CWE-078: Add JSch OS command injection sink
---
.../Security/CWE/CWE-078/ExecCommon.qll | 32 ++++++++++
.../Security/CWE/CWE-078/ExecTainted.ql | 24 +++++++
.../CWE/CWE-078/JSchOSInjection.qhelp | 64 +++++++++++++++++++
.../Security/CWE/CWE-078/JSchOSInjection.qll | 20 ++++++
.../CWE/CWE-078/JSchOSInjectionBad.java | 17 +++++
.../CWE/CWE-078/JSchOSInjectionSanitized.java | 46 +++++++++++++
.../security/CWE-078/ExecTainted.expected | 11 ++++
.../security/CWE-078/ExecTainted.qlref | 1 +
.../security/CWE-078/JSchOSInjectionTest.java | 56 ++++++++++++++++
.../query-tests/security/CWE-078/options | 2 +
.../jsch-0.1.55/com/jcraft/jsch/Channel.java | 46 +++++++++++++
.../com/jcraft/jsch/ChannelExec.java | 40 ++++++++++++
.../com/jcraft/jsch/ChannelSession.java | 33 ++++++++++
.../jsch-0.1.55/com/jcraft/jsch/JSch.java | 40 ++++++++++++
.../jsch-0.1.55/com/jcraft/jsch/Session.java | 55 ++++++++++++++++
15 files changed, 487 insertions(+)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/ExecCommon.qll
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qll
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionBad.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.qlref
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-078/JSchOSInjectionTest.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-078/options
create mode 100644 java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Channel.java
create mode 100644 java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelExec.java
create mode 100644 java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelSession.java
create mode 100644 java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/JSch.java
create mode 100644 java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Session.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/ExecCommon.qll b/java/ql/src/experimental/Security/CWE/CWE-078/ExecCommon.qll
new file mode 100644
index 00000000000..c0025043fce
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/ExecCommon.qll
@@ -0,0 +1,32 @@
+import semmle.code.java.dataflow.FlowSources
+import semmle.code.java.security.ExternalProcess
+import semmle.code.java.security.CommandArguments
+
+private class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
+ RemoteUserInputToArgumentToExecFlowConfig() {
+ this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
+ }
+
+ override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec }
+
+ override predicate isSanitizer(DataFlow::Node node) {
+ node.getType() instanceof PrimitiveType
+ or
+ node.getType() instanceof BoxedType
+ or
+ isSafeCommandArgument(node.asExpr())
+ }
+}
+
+/**
+ * Implementation of `ExecTainted.ql`. It is extracted to a QLL
+ * so that it can be excluded from `ExecUnescaped.ql` to avoid
+ * reporting overlapping results.
+ */
+predicate execTainted(DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg) {
+ exists(RemoteUserInputToArgumentToExecFlowConfig conf |
+ conf.hasFlowPath(source, sink) and sink.getNode() = DataFlow::exprNode(execArg)
+ )
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql b/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql
new file mode 100644
index 00000000000..b73203ecbbc
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql
@@ -0,0 +1,24 @@
+/**
+ * @name Uncontrolled command line
+ * @description Using externally controlled strings in a command line is vulnerable to malicious
+ * changes in the strings.
+ * @kind path-problem
+ * @problem.severity error
+ * @precision high
+ * @id java/command-line-injection
+ * @tags security
+ * external/cwe/cwe-078
+ * external/cwe/cwe-088
+ */
+
+import java
+import semmle.code.java.dataflow.FlowSources
+import semmle.code.java.security.ExternalProcess
+import ExecCommon
+import JSchOSInjection
+import DataFlow::PathGraph
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg
+where execTainted(source, sink, execArg)
+select execArg, source, sink, "$@ flows to here and is used in a command.", source.getNode(),
+ "User-provided value"
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qhelp
new file mode 100644
index 00000000000..57e8a61fe74
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qhelp
@@ -0,0 +1,64 @@
+
+
+
+
+
+JSch is a pure Java implementation of SSH2.
+JSch allows you to connect to a sshd server and use port forwarding, X11 forwarding,
+file transfer, command execution, etc., and you can integrate its functionality into your own Java programs.
+JSch is licensed under BSD style license.
+If an OS command is built using an attacker-controlled data, it may allow the attacker
+to run an arbitrary code on the remote host.
+
+
+
+
+
+Including an user input in a JSch lib's OS command expression should be avoided.
+If this is not possible, then a strong input validation must be performed.
+Some examples of an effective validation include:
+
+Validating against an allowlist of permitted values.
+Validating that the input is a number.
+Validating that the input contains only alphanumeric characters, no other syntax or whitespace.
+
+Never attempt to sanitize input by escaping shell metacharacters. In practice,
+this is just too error-prone and vulnerable to being bypassed by a skilled attacker.
+
+
+
+
+
+
+The following example uses the untrusted data to build an OS command.
+
+
+
+
+
+
+The following example validates the untrusted data before build an OS command.
+
+
+
+
+
+
+ JCraft:
+ JSch - Java Secure Channel.
+
+
+ OWASP:
+ Command Injection.
+
+
+ OWASP:
+ OS Command Injection Defense Cheat Sheet.
+
+
+ PortSwigger:
+ OS command injection.
+
+
+
+
\ No newline at end of file
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qll b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qll
new file mode 100644
index 00000000000..ec1f4d0adfa
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjection.qll
@@ -0,0 +1,20 @@
+/**
+ * Provides classes for JSch OS command injection detection
+ */
+
+import java
+
+/** The class `com.jcraft.jsch.ChannelExec`. */
+private class JSchChannelExec extends RefType {
+ JSchChannelExec() { this.hasQualifiedName("com.jcraft.jsch", "ChannelExec") }
+}
+
+/** A method to set an OS Command for the execution. */
+private class ChannelExecSetCommandMethod extends Method, ExecCallable {
+ ChannelExecSetCommandMethod() {
+ this.hasName("setCommand") and
+ this.getDeclaringType() instanceof JSchChannelExec
+ }
+
+ override int getAnExecutedArgument() { result = 0 }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionBad.java b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionBad.java
new file mode 100644
index 00000000000..ab4c3fb1c06
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionBad.java
@@ -0,0 +1,17 @@
+public class JSchOSInjectionBad {
+ void jschOsExecution(HttpServletRequest request) {
+ String command = request.getParameter("command");
+
+ JSch jsch = new JSch();
+ Session session = jsch.getSession("user", "sshHost", 22);
+ session.setPassword("password");
+ session.connect();
+
+ Channel channel = session.openChannel("exec");
+ // BAD - untrusted user data is used directly in a command
+ ((ChannelExec) channel).setCommand("ping " + command);
+
+ channel.connect();
+ }
+}
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
new file mode 100644
index 00000000000..fdd72e551a0
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
@@ -0,0 +1,46 @@
+public class JSchOSInjectionSanitized {
+ void jschOsExecutionPing(HttpServletRequest request) {
+ String untrusted = request.getParameter("command");
+
+ //GOOD - Validate user the input.
+ if (!com.google.common.net.InetAddresses.isInetAddress(untrusted)) {
+ System.out.println("Invalid IP address");
+ return;
+ }
+
+ JSch jsch = new JSch();
+ Session session = jsch.getSession("user", "host", 22);
+ session.setPassword("password");
+ session.connect();
+
+ Channel channel = session.openChannel("exec");
+ ((ChannelExec) channel).setCommand("ping " + untrusted);
+
+ channel.connect();
+ }
+
+ void jschOsExecutionDig(HttpServletRequest request) {
+ String untrusted = request.getParameter("command");
+
+ //GOOD - check whether the user input doesn't contain dangerous shell characters.
+ String[] badChars = new String[] {"^", "~" ," " , "&", "|", ";", "$", ">", "<", "`", "\\", ",", "!", "{", "}", "(", ")", "@", "%", "#", "%0A", "%0a", "\n", "\r\n"};
+
+ for (String badChar : badChars) {
+ if (untrusted.contains(badChar)) {
+ System.out.println("Invalid IP address");
+ return;
+ }
+ }
+
+ JSch jsch = new JSch();
+ Session session = jsch.getSession("user", "host", 22);
+ session.setPassword("password");
+ session.connect();
+
+ Channel channel = session.openChannel("exec");
+ ((ChannelExec) channel).setCommand("dig " + untrusted);
+
+ channel.connect();
+ }
+}
+
diff --git a/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.expected b/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.expected
new file mode 100644
index 00000000000..6d87a2ffb89
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.expected
@@ -0,0 +1,11 @@
+edges
+| JSchOSInjectionTest.java:14:30:14:60 | getParameter(...) : String | JSchOSInjectionTest.java:26:48:26:64 | ... + ... |
+| JSchOSInjectionTest.java:38:30:38:60 | getParameter(...) : String | JSchOSInjectionTest.java:50:32:50:48 | ... + ... |
+nodes
+| JSchOSInjectionTest.java:14:30:14:60 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JSchOSInjectionTest.java:26:48:26:64 | ... + ... | semmle.label | ... + ... |
+| JSchOSInjectionTest.java:38:30:38:60 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JSchOSInjectionTest.java:50:32:50:48 | ... + ... | semmle.label | ... + ... |
+#select
+| JSchOSInjectionTest.java:26:48:26:64 | ... + ... | JSchOSInjectionTest.java:14:30:14:60 | getParameter(...) : String | JSchOSInjectionTest.java:26:48:26:64 | ... + ... | $@ flows to here and is used in a command. | JSchOSInjectionTest.java:14:30:14:60 | getParameter(...) | User-provided value |
+| JSchOSInjectionTest.java:50:32:50:48 | ... + ... | JSchOSInjectionTest.java:38:30:38:60 | getParameter(...) : String | JSchOSInjectionTest.java:50:32:50:48 | ... + ... | $@ flows to here and is used in a command. | JSchOSInjectionTest.java:38:30:38:60 | getParameter(...) | User-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.qlref b/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.qlref
new file mode 100644
index 00000000000..714c3cadc5f
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-078/ExecTainted.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-078/ExecTainted.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-078/JSchOSInjectionTest.java b/java/ql/test/experimental/query-tests/security/CWE-078/JSchOSInjectionTest.java
new file mode 100644
index 00000000000..08baf0a9772
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-078/JSchOSInjectionTest.java
@@ -0,0 +1,56 @@
+import com.jcraft.jsch.*;
+
+import javax.servlet.http.*;
+import javax.servlet.ServletException;
+import java.io.IOException;
+
+public class JSchOSInjectionTest extends HttpServlet {
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String host = "sshHost";
+ String user = "user";
+ String password = "password";
+ String command = request.getParameter("command");
+
+ java.util.Properties config = new java.util.Properties();
+ config.put("StrictHostKeyChecking", "no");
+
+ JSch jsch = new JSch();
+ Session session = jsch.getSession(user, host, 22);
+ session.setPassword(password);
+ session.setConfig(config);
+ session.connect();
+
+ Channel channel = session.openChannel("exec");
+ ((ChannelExec) channel).setCommand("ping " + command);
+ channel.setInputStream(null);
+ ((ChannelExec) channel).setErrStream(System.err);
+
+ channel.connect();
+ }
+
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String host = "sshHost";
+ String user = "user";
+ String password = "password";
+ String command = request.getParameter("command");
+
+ java.util.Properties config = new java.util.Properties();
+ config.put("StrictHostKeyChecking", "no");
+
+ JSch jsch = new JSch();
+ Session session = jsch.getSession(user, host, 22);
+ session.setPassword(password);
+ session.setConfig(config);
+ session.connect();
+
+ ChannelExec channel = (ChannelExec)session.openChannel("exec");
+ channel.setCommand("ping " + command);
+ channel.setInputStream(null);
+ channel.setErrStream(System.err);
+
+ channel.connect();
+ }
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-078/options b/java/ql/test/experimental/query-tests/security/CWE-078/options
new file mode 100644
index 00000000000..eb7209ebe1e
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-078/options
@@ -0,0 +1,2 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jsch-0.1.55
+
diff --git a/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Channel.java b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Channel.java
new file mode 100644
index 00000000000..5b084813c61
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Channel.java
@@ -0,0 +1,46 @@
+/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
+/*
+Copyright (c) 2002-2018 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.jcraft.jsch;
+
+import java.io.*;
+
+public abstract class Channel implements Runnable {
+ public void connect() {
+ }
+
+ public void setInputStream(InputStream in){
+ }
+
+ public void disconnect(){
+ }
+
+ public void run() {
+ }
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelExec.java b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelExec.java
new file mode 100644
index 00000000000..6ff67754d99
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelExec.java
@@ -0,0 +1,40 @@
+/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
+/*
+Copyright (c) 2002-2018 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.jcraft.jsch;
+
+import java.io.*;
+
+public class ChannelExec extends ChannelSession {
+ public void setErrStream(OutputStream out) {
+ }
+
+ public void setCommand(String command){
+ }
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelSession.java b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelSession.java
new file mode 100644
index 00000000000..a6c97b334b6
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/ChannelSession.java
@@ -0,0 +1,33 @@
+/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
+/*
+Copyright (c) 2002-2018 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.jcraft.jsch;
+
+class ChannelSession extends Channel {
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/JSch.java b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/JSch.java
new file mode 100644
index 00000000000..b8ce91b9715
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/JSch.java
@@ -0,0 +1,40 @@
+/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
+/*
+Copyright (c) 2002-2018 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.jcraft.jsch;
+
+public class JSch {
+
+ public JSch() {}
+
+ public Session getSession(String username, String host, int port) {
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Session.java b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Session.java
new file mode 100644
index 00000000000..4cf2015fceb
--- /dev/null
+++ b/java/ql/test/experimental/stubs/jsch-0.1.55/com/jcraft/jsch/Session.java
@@ -0,0 +1,55 @@
+/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
+/*
+Copyright (c) 2002-2018 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.jcraft.jsch;
+
+public class Session implements Runnable {
+
+ public Channel openChannel(String type) {
+ if ("exec".equals(type))
+ return new ChannelExec();
+
+ return null;
+ }
+
+ public void setPassword(String password) {
+ }
+
+ public void setConfig(java.util.Properties newconf) {
+ }
+
+ public void connect() {
+ }
+
+ public void run(){
+ }
+
+ public void disconnect(){
+ }
+}
\ No newline at end of file
From 7455b1b4f08d15029d82a4dee6b5c1143e7b95ae Mon Sep 17 00:00:00 2001
From: Hayk Andriasyan <77549590+p0wn4j@users.noreply.github.com>
Date: Mon, 26 Apr 2021 15:17:57 +0400
Subject: [PATCH 096/550] Update JSchOSInjectionSanitized.java
---
.../Security/CWE/CWE-078/JSchOSInjectionSanitized.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
index fdd72e551a0..b47a2b82ed7 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
+++ b/java/ql/src/experimental/Security/CWE/CWE-078/JSchOSInjectionSanitized.java
@@ -27,7 +27,7 @@ public class JSchOSInjectionSanitized {
for (String badChar : badChars) {
if (untrusted.contains(badChar)) {
- System.out.println("Invalid IP address");
+ System.out.println("Invalid host");
return;
}
}
From b7de370918e4b193b855ccae6fa491fcf6f5726a Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Mon, 26 Apr 2021 23:04:08 +0300
Subject: [PATCH 097/550] Add files via upload
---
.../Security/CWE/CWE-415/DoubleFree.ql | 63 +++++++++----------
1 file changed, 28 insertions(+), 35 deletions(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
index 199dc18bee7..bb799ec4d52 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql
@@ -12,40 +12,33 @@
import cpp
-/**
- * The function allows `getASuccessor` to be called recursively.
- * This provides a stop in situations of possible influence on the pointer.
- */
-ControlFlowNode recursASuccessor(FunctionCall fc, LocalScopeVariable v) {
- result = fc
- or
- exists(ControlFlowNode mid |
- mid = recursASuccessor(fc, v) and
- result = mid.getASuccessor() and
- not result = v.getAnAssignedValue() and
- not result.(AddressOfExpr).getOperand() = v.getAnAccess() and
- not (
- not result instanceof DeallocationExpr and
- result.(FunctionCall).getAnArgument().(VariableAccess).getTarget() = v
- ) and
- (
- fc.getTarget().hasGlobalOrStdName("realloc") and
- (
- not fc.getParent*() instanceof IfStmt and
- not result instanceof IfStmt
- )
- or
- not fc.getTarget().hasGlobalOrStdName("realloc")
- )
- )
-}
-
-from FunctionCall fc
+from FunctionCall fc, FunctionCall fc2, LocalScopeVariable v
where
- exists(FunctionCall fc2, LocalScopeVariable v |
- freeCall(fc, v.getAnAccess()) and
- freeCall(fc2, v.getAnAccess()) and
- fc != fc2 and
- recursASuccessor(fc, v) = fc2
+ freeCall(fc, v.getAnAccess()) and
+ freeCall(fc2, v.getAnAccess()) and
+ fc != fc2 and
+ fc.getASuccessor*() = fc2 and
+ not exists(Expr exptmp |
+ (exptmp = v.getAnAssignedValue() or exptmp.(AddressOfExpr).getOperand() = v.getAnAccess()) and
+ exptmp = fc.getASuccessor*() and
+ exptmp = fc2.getAPredecessor*()
+ ) and
+ not exists(FunctionCall fctmp |
+ not fctmp instanceof DeallocationExpr and
+ fctmp = fc.getASuccessor*() and
+ fctmp = fc2.getAPredecessor*() and
+ fctmp.getAnArgument().(VariableAccess).getTarget() = v
+ ) and
+ (
+ fc.getTarget().hasGlobalOrStdName("realloc") and
+ (
+ not fc.getParent*() instanceof IfStmt and
+ not exists(IfStmt iftmp |
+ iftmp.getCondition().getAChild*().(VariableAccess).getTarget().getAnAssignedValue() = fc
+ )
+ )
+ or
+ not fc.getTarget().hasGlobalOrStdName("realloc")
)
-select fc.getArgument(0), "This pointer may be cleared again later."
+select fc2.getArgument(0),
+ "This pointer may have already been cleared in the line " + fc.getLocation().getStartLine() + "."
From c31a761750e68916fb2a4bb8517ea9026d4ad87c Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Mon, 26 Apr 2021 23:05:08 +0300
Subject: [PATCH 098/550] Add files via upload
---
.../CWE-415/semmle/tests/DoubleFree.expected | 6 +-
.../Security/CWE/CWE-415/semmle/tests/test.c | 87 +++++++++++++++++--
2 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
index 669c65cba2a..0ab66e5b26c 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/DoubleFree.expected
@@ -1,2 +1,4 @@
-| test.c:9:8:9:10 | buf | This pointer may be cleared again later. |
-| test.c:19:26:19:29 | buf1 | This pointer may be cleared again later. |
+| test.c:11:16:11:18 | buf | This pointer may have already been cleared in the line 10. |
+| test.c:18:8:18:10 | buf | This pointer may have already been cleared in the line 17. |
+| test.c:57:8:57:10 | buf | This pointer may have already been cleared in the line 55. |
+| test.c:78:8:78:10 | buf | This pointer may have already been cleared in the line 77. |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
index 1ebf3546480..c9be64a645c 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
@@ -1,21 +1,96 @@
typedef unsigned long size_t;
void *malloc(size_t size);
void free(void *ptr);
+#define NULL 0
void workFunction_0(char *s) {
int intSize = 10;
char *buf;
buf = (char *) malloc(intSize);
- free(buf); // BAD
- if(buf) free(buf);
+ free(buf); // GOOD
+ if(buf) free(buf); // BAD
}
void workFunction_1(char *s) {
+ int intSize = 10;
+ char *buf;
+ buf = (char *) malloc(intSize);
+ free(buf); // GOOD
+ free(buf); // BAD
+}
+void workFunction_2(char *s) {
+ int intSize = 10;
+ char *buf;
+ buf = (char *) malloc(intSize);
+ free(buf); // GOOD
+ buf = NULL;
+ free(buf);
+}
+void workFunction_3(char *s) {
+ int intSize = 10;
+ char *buf;
+ int intFlag;
+ buf = (char *) malloc(intSize);
+ if(buf[1]%5) {
+ free(buf);
+ buf = NULL;
+ }
+ free(buf);
+}
+void workFunction_4(char *s) {
+ int intSize = 10;
+ char *buf;
+ char *tmpbuf;
+ tmpbuf = (char *) malloc(intSize);
+ buf = (char *) malloc(intSize);
+ free(buf); // GOOD
+ buf = tmpbuf;
+ free(buf); // GOOD
+}
+void workFunction_5(char *s) {
+ int intSize = 10;
+ char *buf;
+ int intFlag;
+ buf = (char *) malloc(intSize);
+ if(intFlag) {
+ free(buf);
+ }
+ free(buf); // BAD
+}
+void workFunction_6(char *s) {
+ int intSize = 10;
+ char *buf;
+ char *tmpbuf;
+ int intFlag;
+ tmpbuf = (char *) malloc(intSize);
+ buf = (char *) malloc(intSize);
+ if(intFlag) {
+ free(buf);
+ buf = tmpbuf;
+ }
+ free(buf);
+}
+void workFunction_7(char *s) {
int intSize = 10;
char *buf;
char *buf1;
buf = (char *) malloc(intSize);
- buf1 = (char *) realloc(buf,intSize*2);
- if(buf) free(buf); // GOOD
- buf = (char *) realloc(buf1,intSize*4); // BAD
- free(buf1);
+ buf1 = (char *) realloc(buf,intSize*4);
+ free(buf); // BAD
+}
+void workFunction_8(char *s) {
+ int intSize = 10;
+ char *buf;
+ char *buf1;
+ buf = (char *) malloc(intSize);
+ buf1 = (char *) realloc(buf,intSize*4);
+ if(!buf1)
+ free(buf); // GOOD
+}
+void workFunction_9(char *s) {
+ int intSize = 10;
+ char *buf;
+ char *buf1;
+ buf = (char *) malloc(intSize);
+ if(!(buf1 = (char *) realloc(buf,intSize*4)))
+ free(buf); // GOOD
}
From 0c3e2b9ab7e54cc6585d93132cea2a3a358f437f Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Tue, 27 Apr 2021 10:11:32 +0300
Subject: [PATCH 099/550] Update test.c
---
.../Security/CWE/CWE-415/semmle/tests/test.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
index c9be64a645c..22cd6a536f4 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-415/semmle/tests/test.c
@@ -23,7 +23,7 @@ void workFunction_2(char *s) {
buf = (char *) malloc(intSize);
free(buf); // GOOD
buf = NULL;
- free(buf);
+ free(buf); // GOOD
}
void workFunction_3(char *s) {
int intSize = 10;
@@ -31,10 +31,10 @@ void workFunction_3(char *s) {
int intFlag;
buf = (char *) malloc(intSize);
if(buf[1]%5) {
- free(buf);
+ free(buf); // GOOD
buf = NULL;
}
- free(buf);
+ free(buf); // GOOD
}
void workFunction_4(char *s) {
int intSize = 10;
@@ -52,7 +52,7 @@ void workFunction_5(char *s) {
int intFlag;
buf = (char *) malloc(intSize);
if(intFlag) {
- free(buf);
+ free(buf); // GOOD
}
free(buf); // BAD
}
@@ -64,10 +64,10 @@ void workFunction_6(char *s) {
tmpbuf = (char *) malloc(intSize);
buf = (char *) malloc(intSize);
if(intFlag) {
- free(buf);
+ free(buf); // GOOD
buf = tmpbuf;
}
- free(buf);
+ free(buf); // GOOD
}
void workFunction_7(char *s) {
int intSize = 10;
From 044c92016bd89438f8ba135a65717f13c6d52d7b Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 11:52:26 +0200
Subject: [PATCH 100/550] Data flow: Cache enclosing callable predicates
---
.../dataflow/internal/DataFlowImplCommon.qll | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index a51c20c2288..b5cc2438456 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -242,6 +242,14 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ cached
+ predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
+
+ cached
+ predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
+ c = call.getEnclosingCallable()
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -553,7 +561,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
- callable = call.getEnclosingCallable() and
+ callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +619,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
- tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
+ tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -866,7 +874,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
- exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
+ exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -1017,7 +1025,7 @@ pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
exists(Node n0 |
pragma[only_bind_into](n0) = n and
- pragma[only_bind_into](result) = n0.getEnclosingCallable()
+ nodeEnclosingCallable(n0, pragma[only_bind_into](result))
)
}
@@ -1042,7 +1050,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
- call0.getEnclosingCallable() = callable and
+ callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
From 1a56f0b79ce8edf7f7d577e599e49c2f51cdf32b Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 11:58:00 +0200
Subject: [PATCH 101/550] Data flow: Cache `getNodeType`
---
.../csharp/dataflow/internal/DataFlowImpl.qll | 28 ++++++-----
.../dataflow/internal/DataFlowImplCommon.qll | 48 +++++++++++--------
2 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 9498e51e7e6..4dbf1b0cdaa 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -1327,11 +1327,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
@@ -1350,7 +1350,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1384,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1443,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -2088,7 +2090,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2758,7 +2760,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -3148,7 +3150,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3591,7 +3593,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3627,7 +3629,7 @@ private module FlowExploration {
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3797,7 +3799,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3815,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3829,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index b5cc2438456..a6f04cb8ce9 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -119,7 +119,7 @@ private module LambdaFlow {
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
- then compatibleTypes(t, getNodeType(node))
+ then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +129,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
- t = getNodeType(node) and
+ t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +146,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -168,7 +168,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -250,6 +250,9 @@ private module Cached {
c = call.getEnclosingCallable()
}
+ cached
+ predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -282,7 +285,7 @@ private module Cached {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
- compatibleTypes(getNodeType(arg), getNodeType(p))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -430,10 +433,10 @@ private module Cached {
then
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(p), getNodeType(node))
+ compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
- compatibleTypes(read.getContentType(), getNodeType(node))
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
@@ -455,7 +458,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
- compatibleTypes(getNodeType(p), read.getContainerType())
+ compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -511,11 +514,11 @@ private module Cached {
|
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(arg), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
- compatibleTypes(getNodeType(arg), read.getContainerType()) and
- compatibleTypes(read.getContentType(), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -653,8 +656,8 @@ private module Cached {
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
- contentType = getNodeType(node1) and
- containerType = getNodeType(node2)
+ contentType = getNodeDataFlowType(node1) and
+ containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -663,8 +666,8 @@ private module Cached {
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
- contentType = getNodeType(n1) and
- containerType = getNodeType(n2)
+ contentType = getNodeDataFlowType(n1) and
+ containerType = getNodeDataFlowType(n2)
)
}
@@ -784,8 +787,8 @@ private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
- container = getNodeType(n1) and
- content = getNodeType(n2)
+ container = getNodeDataFlowType(n1) and
+ content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -1023,10 +1026,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
- exists(Node n0 |
- pragma[only_bind_into](n0) = n and
- nodeEnclosingCallable(n0, pragma[only_bind_into](result))
- )
+ nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
+}
+
+/** Gets the type of `n` used for type pruning. */
+pragma[inline]
+DataFlowType getNodeDataFlowType(Node n) {
+ nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
From 8bfeae768faac60bcdc8de1cc59664d1982e728a Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 13:16:54 +0200
Subject: [PATCH 102/550] Data flow: Cache `simpleLocalFlowStep`
---
.../code/csharp/dataflow/internal/DataFlowImpl.qll | 5 +----
.../csharp/dataflow/internal/DataFlowImplCommon.qll | 11 +++++++++--
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 4dbf1b0cdaa..7bf05143cfa 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index a6f04cb8ce9..87034b74fde 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -689,8 +689,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
- cached
- predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
+ private predicate reverseStepThroughInputOutputAlias(
+ PostUpdateNode fromNode, PostUpdateNode toNode
+ ) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -707,6 +708,12 @@ private module Cached {
)
}
+ cached
+ predicate simpleLocalFlowStepExt(Node node1, Node node2) {
+ simpleLocalFlowStep(node1, node2) or
+ reverseStepThroughInputOutputAlias(node1, node2)
+ }
+
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
From 96aa1828935984adfdaa6b50abc566c79f94e79f Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 13:22:37 +0200
Subject: [PATCH 103/550] Data flow: Cache `jumpStep`
---
.../semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 2 +-
.../code/csharp/dataflow/internal/DataFlowImplCommon.qll | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 7bf05143cfa..938a7b3fe2f 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -234,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index 87034b74fde..32e0f913015 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -160,7 +160,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
- jumpStep(node, mid) and
+ jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -253,6 +253,9 @@ private module Cached {
cached
predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+ cached
+ predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+
/**
* Gets a viable target for the lambda call `call`.
*
From 4009c01558472839f32c006507505749bf864a57 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 15:52:22 +0200
Subject: [PATCH 104/550] Data flow: Cache `readStep`
---
.../dataflow/internal/DataFlowImplCommon.qll | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index 32e0f913015..3a245cda11a 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -339,7 +339,7 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
- readStep(mid, _, node) and
+ read(mid, _, node) and
read = true
)
or
@@ -658,7 +658,7 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
- readStep(_, c, _) and
+ read(_, c, _) and
contentType = getNodeDataFlowType(node1) and
containerType = getNodeDataFlowType(node2)
or
@@ -668,12 +668,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
- readStep(n2, c, n1) and
+ read(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
containerType = getNodeDataFlowType(n2)
)
}
+ cached
+ predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
+
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -789,14 +792,14 @@ class CastingNode extends Node {
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
// the type of `x.f`.
- readStep(_, _, this)
+ read(_, _, this)
}
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
- readStep(n1, c, n2) and
+ read(n1, c, n2) and
container = getNodeDataFlowType(n1) and
content = getNodeDataFlowType(n2)
}
@@ -1087,8 +1090,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
-predicate read = readStep/3;
-
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
From 1bf0e01a83c224632864d4825f5d9f67b69866d0 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 15:55:52 +0200
Subject: [PATCH 105/550] Data flow: Cache `clearsContent`
---
.../semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 6 +++---
.../code/csharp/dataflow/internal/DataFlowImplCommon.qll | 5 ++++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 938a7b3fe2f..4099043f4d8 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -1258,7 +1258,7 @@ private module LocalFlowBigStep {
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
- clearsContent(this, _)
+ clearsContentCached(this, _)
}
}
@@ -3610,7 +3610,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3624,7 +3624,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index 3a245cda11a..e8260dd3c8c 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -256,6 +256,9 @@ private module Cached {
cached
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+ cached
+ predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -1141,7 +1144,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
- predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
+ predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
From 23113c4ff7002828421630e34febca601341a826 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 23 Apr 2021 16:11:08 +0200
Subject: [PATCH 106/550] Data flow: Cache `isUnreachableInCall`
---
.../code/csharp/dataflow/internal/DataFlowImpl.qll | 6 +++---
.../code/csharp/dataflow/internal/DataFlowImplCommon.qll | 9 ++++++---
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 4099043f4d8..68fde153549 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -1318,7 +1318,7 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
@@ -1332,7 +1332,7 @@ private module LocalFlowBigStep {
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -3782,7 +3782,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index e8260dd3c8c..f3b005ff148 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -259,6 +259,9 @@ private module Cached {
cached
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+ cached
+ predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -731,7 +734,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
- exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -753,7 +756,7 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
- TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
+ TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
@@ -926,7 +929,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
- exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
From 9738de2cb9487c52580dc595bea0f8efbd3066fd Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 15:28:20 +0200
Subject: [PATCH 107/550] Data flow: Cache `OutNodeExt`
---
.../dataflow/internal/DataFlowImplCommon.qll | 36 ++++++++++---------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index f3b005ff148..d6fbadd21f0 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -262,6 +262,23 @@ private module Cached {
cached
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+ cached
+ predicate outNodeExt(Node n) {
+ n instanceof OutNode
+ or
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
+ }
+
+ cached
+ OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
+ result = getAnOutNode(call, k.(ValueReturnKind).getKind())
+ or
+ exists(ArgumentNode arg |
+ result.(PostUpdateNode).getPreUpdateNode() = arg and
+ arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
+ )
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -970,11 +987,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
- OutNodeExt() {
- this instanceof OutNode
- or
- this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
- }
+ OutNodeExt() { outNodeExt(this) }
}
/**
@@ -987,7 +1000,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
- abstract OutNodeExt getAnOutNode(DataFlowCall call);
+ final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -998,10 +1011,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- result = getAnOutNode(call, this.getKind())
- }
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -1012,13 +1021,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- exists(ArgumentNode arg |
- result.(PostUpdateNode).getPreUpdateNode() = arg and
- arg.argumentOf(call, this.getPosition())
- )
- }
}
/** A callable tagged with a relevant return kind. */
From 346af4f97adf1c650ee4168352667c3de867bd69 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 15:30:01 +0200
Subject: [PATCH 108/550] Data flow: Cache `ReturnNodeExt`
---
.../dataflow/internal/DataFlowImplCommon.qll | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index d6fbadd21f0..c81af6cde57 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -279,6 +279,17 @@ private module Cached {
)
}
+ cached
+ predicate returnNodeExt(Node n, ReturnKindExt k) {
+ k = TValueReturn(n.(ReturnNode).getKind())
+ or
+ exists(ParameterNode p, int pos |
+ parameterValueFlowsToPreUpdate(p, n) and
+ p.isParameterOf(_, pos) and
+ k = TParamUpdate(pos)
+ )
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -672,8 +683,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- cached
- predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -965,21 +975,10 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
- ReturnNodeExt() {
- this instanceof ReturnNode or
- parameterValueFlowsToPreUpdate(_, this)
- }
+ ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
- ReturnKindExt getKind() {
- result = TValueReturn(this.(ReturnNode).getKind())
- or
- exists(ParameterNode p, int pos |
- parameterValueFlowsToPreUpdate(p, this) and
- p.isParameterOf(_, pos) and
- result = TParamUpdate(pos)
- )
- }
+ ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
From ade99c2c2b104d7b5cc5295553a8e82da328bcae Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 15:37:43 +0200
Subject: [PATCH 109/550] Data flow: Cache `Cast(ing)Node`
---
.../csharp/dataflow/internal/DataFlowImpl.qll | 2 +-
.../dataflow/internal/DataFlowImplCommon.qll | 26 ++++++++++++-------
2 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 68fde153549..242d5444d38 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -1257,7 +1257,7 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
+ castNode(this) or
clearsContentCached(this, _)
}
}
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index c81af6cde57..d9e875ee281 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -118,7 +118,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgumentNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -290,6 +290,20 @@ private module Cached {
)
}
+ cached
+ predicate castNode(Node n) { n instanceof CastNode }
+
+ cached
+ predicate castingNode(Node n) {
+ castNode(n) or
+ n instanceof ParameterNode or
+ n instanceof OutNodeExt or
+ // For reads, `x.f`, we want to check that the tracked type after the read (which
+ // is obtained by popping the head of the access path stack) is compatible with
+ // the type of `x.f`.
+ read(_, _, n)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -818,15 +832,7 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
- CastingNode() {
- this instanceof ParameterNode or
- this instanceof CastNode or
- this instanceof OutNodeExt or
- // For reads, `x.f`, we want to check that the tracked type after the read (which
- // is obtained by popping the head of the access path stack) is compatible with
- // the type of `x.f`.
- read(_, _, this)
- }
+ CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
From 7d4feaca2f421acd7241621d93e4d357bc721059 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 15:44:22 +0200
Subject: [PATCH 110/550] Data flow: Cache `ArgumentNode`
---
.../csharp/dataflow/internal/DataFlowImpl.qll | 42 +++++++--------
.../dataflow/internal/DataFlowImplCommon.qll | 51 ++++++++++++-------
2 files changed, 53 insertions(+), 40 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 242d5444d38..53a8ebe2d54 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -520,7 +520,7 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
exists(ParameterNode p |
revFlow(p, toReturn, config) and
@@ -529,7 +529,7 @@ private module Stage1 {
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -660,7 +660,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -672,7 +672,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -732,7 +732,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,7 +944,7 @@ private module Stage2 {
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1130,7 +1130,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -1143,7 +1143,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1242,7 +1242,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1585,7 +1585,7 @@ private module Stage3 {
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1771,7 +1771,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -1784,7 +1784,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2154,7 +2154,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2302,7 +2302,7 @@ private module Stage4 {
DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2488,7 +2488,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(ParameterNode p, boolean allowsFieldFlow |
@@ -2501,7 +2501,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -3234,7 +3234,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3923,7 +3923,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -4137,7 +4137,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index d9e875ee281..f079d878dec 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -43,14 +43,14 @@ private module LambdaFlow {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,7 +118,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if castNode(node) or node instanceof ArgumentNode or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -266,14 +266,14 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
}
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -304,6 +304,11 @@ private module Cached {
read(_, _, n)
}
+ cached
+ predicate argumentNode(Node n, DataFlowCall call, int pos) {
+ n.(ArgumentNode).argumentOf(call, pos)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -332,7 +337,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -392,20 +397,20 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
+ private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNodeExt arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
@@ -431,7 +436,7 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
@@ -444,7 +449,7 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -520,13 +525,13 @@ private module Cached {
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
@@ -534,7 +539,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
+ ParameterNode p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -542,7 +547,7 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
exists(ParameterNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
@@ -558,7 +563,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -578,7 +583,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNode arg, Content c, Node out) {
+ predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -753,8 +758,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNode).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
+ toPre.(ArgumentNodeExt).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -976,6 +981,14 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/** A data-flow node that represents a call argument. */
+class ArgumentNodeExt extends Node {
+ ArgumentNodeExt() { argumentNode(this, _, _) }
+
+ /** Holds if this argument occurs at the given position in the given call. */
+ final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+}
+
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
From 1112c0f9942f237d362aabd8afc715a5175b949a Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 15:50:00 +0200
Subject: [PATCH 111/550] Data flow: Cache `ParameterNode`
---
.../csharp/dataflow/internal/DataFlowImpl.qll | 74 ++++++++++--------
.../dataflow/internal/DataFlowImplCommon.qll | 75 ++++++++++++-------
2 files changed, 90 insertions(+), 59 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index 53a8ebe2d54..ede9390bace 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -512,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -522,7 +522,7 @@ private module Stage1 {
private predicate revFlowIn(
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
@@ -594,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -660,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -672,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -732,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -941,7 +943,7 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
@@ -989,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,7 +1135,7 @@ private module Stage2 {
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1196,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1242,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1272,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1582,7 +1586,7 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
@@ -1630,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1774,7 +1778,7 @@ private module Stage3 {
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1837,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2154,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2299,7 +2305,7 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
@@ -2347,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2491,7 +2497,7 @@ private module Stage4 {
DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2554,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2605,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2626,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3247,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3271,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3567,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3942,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3979,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4036,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4114,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index f079d878dec..a9a19ed322d 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -35,22 +35,24 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
+ private predicate viableParamArgNonLambda(
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
+ ) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -176,7 +178,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,8 +229,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
- DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
+ boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -283,7 +285,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNode p, int pos |
+ exists(ParameterNodeExt p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -296,7 +298,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNode or
+ n instanceof ParameterNodeExt or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -304,6 +306,11 @@ private module Cached {
read(_, _, n)
}
+ cached
+ predicate parameterNode(Node n, DataFlowCallable c, int i) {
+ n.(ParameterNode).isParameterOf(c, i)
+ }
+
cached
predicate argumentNode(Node n, DataFlowCall call, int pos) {
n.(ArgumentNode).argumentOf(call, pos)
@@ -328,7 +335,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -337,7 +344,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -379,7 +386,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
p = node and
read = false
or
@@ -410,12 +417,14 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNodeExt arg, boolean read) {
+ private predicate parameterValueFlowArgCand(
+ ParameterNodeExt p, ArgumentNodeExt arg, boolean read
+ ) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -427,7 +436,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -438,7 +447,7 @@ private module Cached {
private predicate argumentValueFlowsThroughCand0(
DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -456,7 +465,7 @@ private module Cached {
)
}
- predicate cand(ParameterNode p, Node n) {
+ predicate cand(ParameterNodeExt p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -483,7 +492,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -497,7 +506,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -522,7 +531,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNodeExt arg |
@@ -539,7 +548,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNodeExt arg, ReadStepTypesOption read
+ ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -549,7 +558,7 @@ private module Cached {
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -596,7 +605,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNode p, ReturnKind kind, ReadStepTypesOption read
+ ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -702,7 +711,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -807,7 +816,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -922,7 +931,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
+ exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -981,6 +990,20 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/**
+ * The value of a parameter at function entry, viewed as a node in a data
+ * flow graph.
+ */
+class ParameterNodeExt extends Node {
+ ParameterNodeExt() { parameterNode(this, _, _) }
+
+ /**
+ * Holds if this node is the parameter of callable `c` at the specified
+ * (zero-based) position.
+ */
+ predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+}
+
/** A data-flow node that represents a call argument. */
class ArgumentNodeExt extends Node {
ArgumentNodeExt() { argumentNode(this, _, _) }
From 0c8886967bb53b7ac3c5f81b4650aa22fcc09764 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 16:38:17 +0200
Subject: [PATCH 112/550] Data flow: Cache `nodeIsHidden`
---
.../code/csharp/dataflow/internal/DataFlowImpl.qll | 2 +-
.../csharp/dataflow/internal/DataFlowImplCommon.qll | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
index ede9390bace..cf83530bcbd 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll
@@ -2986,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
index a9a19ed322d..b5ceabc605d 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -244,6 +244,14 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ /**
+ * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
+ * force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
+ * collapsing the two stages.
+ */
+ cached
+ predicate forceCachingInSameStage() { any() }
+
cached
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
@@ -271,6 +279,9 @@ private module Cached {
n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
}
+ cached
+ predicate hiddenNode(Node n) { nodeIsHidden(n) }
+
cached
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
From 914184f3dd08969b0709104be32287a6779ad243 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 17:02:20 +0200
Subject: [PATCH 113/550] Data flow: Sync files
---
.../cpp/dataflow/internal/DataFlowImpl.qll | 155 ++++-----
.../cpp/dataflow/internal/DataFlowImpl2.qll | 155 ++++-----
.../cpp/dataflow/internal/DataFlowImpl3.qll | 155 ++++-----
.../cpp/dataflow/internal/DataFlowImpl4.qll | 155 ++++-----
.../dataflow/internal/DataFlowImplCommon.qll | 313 +++++++++++-------
.../dataflow/internal/DataFlowImplLocal.qll | 155 ++++-----
.../cpp/ir/dataflow/internal/DataFlowImpl.qll | 155 ++++-----
.../ir/dataflow/internal/DataFlowImpl2.qll | 155 ++++-----
.../ir/dataflow/internal/DataFlowImpl3.qll | 155 ++++-----
.../ir/dataflow/internal/DataFlowImpl4.qll | 155 ++++-----
.../dataflow/internal/DataFlowImplCommon.qll | 313 +++++++++++-------
.../dataflow/internal/DataFlowImpl2.qll | 155 ++++-----
.../dataflow/internal/DataFlowImpl3.qll | 155 ++++-----
.../dataflow/internal/DataFlowImpl4.qll | 155 ++++-----
.../dataflow/internal/DataFlowImpl5.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl2.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl3.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl4.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl5.qll | 155 ++++-----
.../java/dataflow/internal/DataFlowImpl6.qll | 155 ++++-----
.../dataflow/internal/DataFlowImplCommon.qll | 313 +++++++++++-------
.../dataflow/new/internal/DataFlowImpl.qll | 155 ++++-----
.../dataflow/new/internal/DataFlowImpl2.qll | 155 ++++-----
.../dataflow/new/internal/DataFlowImpl3.qll | 155 ++++-----
.../dataflow/new/internal/DataFlowImpl4.qll | 155 ++++-----
.../new/internal/DataFlowImplCommon.qll | 313 +++++++++++-------
27 files changed, 2659 insertions(+), 2158 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll
index a51c20c2288..b5ceabc605d 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll
@@ -35,22 +35,24 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgNonLambda(
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
+ ) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +120,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
- then compatibleTypes(t, getNodeType(node))
+ if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
+ then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +131,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
- t = getNodeType(node) and
+ t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +148,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +162,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
- jumpStep(node, mid) and
+ jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +170,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +178,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,8 +229,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
- DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
+ boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -242,6 +244,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ /**
+ * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
+ * force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
+ * collapsing the two stages.
+ */
+ cached
+ predicate forceCachingInSameStage() { any() }
+
+ cached
+ predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
+
+ cached
+ predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
+ c = call.getEnclosingCallable()
+ }
+
+ cached
+ predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+
+ cached
+ predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+
+ cached
+ predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+
+ cached
+ predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+
+ cached
+ predicate outNodeExt(Node n) {
+ n instanceof OutNode
+ or
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ }
+
+ cached
+ predicate hiddenNode(Node n) { nodeIsHidden(n) }
+
+ cached
+ OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
+ result = getAnOutNode(call, k.(ValueReturnKind).getKind())
+ or
+ exists(ArgumentNodeExt arg |
+ result.(PostUpdateNode).getPreUpdateNode() = arg and
+ arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
+ )
+ }
+
+ cached
+ predicate returnNodeExt(Node n, ReturnKindExt k) {
+ k = TValueReturn(n.(ReturnNode).getKind())
+ or
+ exists(ParameterNodeExt p, int pos |
+ parameterValueFlowsToPreUpdate(p, n) and
+ p.isParameterOf(_, pos) and
+ k = TParamUpdate(pos)
+ )
+ }
+
+ cached
+ predicate castNode(Node n) { n instanceof CastNode }
+
+ cached
+ predicate castingNode(Node n) {
+ castNode(n) or
+ n instanceof ParameterNodeExt or
+ n instanceof OutNodeExt or
+ // For reads, `x.f`, we want to check that the tracked type after the read (which
+ // is obtained by popping the head of the access path stack) is compatible with
+ // the type of `x.f`.
+ read(_, _, n)
+ }
+
+ cached
+ predicate parameterNode(Node n, DataFlowCallable c, int i) {
+ n.(ParameterNode).isParameterOf(c, i)
+ }
+
+ cached
+ predicate argumentNode(Node n, DataFlowCall call, int pos) {
+ n.(ArgumentNode).argumentOf(call, pos)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +346,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +355,11 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
- compatibleTypes(getNodeType(arg), getNodeType(p))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +397,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +410,32 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
- readStep(mid, _, node) and
+ read(mid, _, node) and
read = true
)
or
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
+ private predicate parameterValueFlowArgCand(
+ ParameterNodeExt p, ArgumentNodeExt arg, boolean read
+ ) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +447,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +456,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +469,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNode p, Node n) {
+ predicate cand(ParameterNodeExt p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +503,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(p), getNodeType(node))
+ compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
- compatibleTypes(read.getContentType(), getNodeType(node))
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +534,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
- compatibleTypes(getNodeType(p), read.getContainerType())
+ compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,16 +542,16 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
@@ -472,7 +559,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
+ ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -480,9 +567,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +583,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(arg), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
- compatibleTypes(getNodeType(arg), read.getContainerType()) and
- compatibleTypes(read.getContentType(), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +603,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNode arg, Content c, Node out) {
+ predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +616,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNode p, ReturnKind kind, ReadStepTypesOption read
+ ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +640,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
- callable = call.getEnclosingCallable() and
+ callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +698,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
- tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
+ tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +722,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- cached
- predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +730,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
- readStep(_, c, _) and
- contentType = getNodeType(node1) and
- containerType = getNodeType(node2)
+ read(_, c, _) and
+ contentType = getNodeDataFlowType(node1) and
+ containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +740,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
- readStep(n2, c, n1) and
- contentType = getNodeType(n1) and
- containerType = getNodeType(n2)
+ read(n2, c, n1) and
+ contentType = getNodeDataFlowType(n1) and
+ containerType = getNodeDataFlowType(n2)
)
}
+ cached
+ predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
+
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +767,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
- cached
- predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
+ private predicate reverseStepThroughInputOutputAlias(
+ PostUpdateNode fromNode, PostUpdateNode toNode
+ ) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +778,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNode).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
+ toPre.(ArgumentNodeExt).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
+ cached
+ predicate simpleLocalFlowStepExt(Node node1, Node node2) {
+ simpleLocalFlowStep(node1, node2) or
+ reverseStepThroughInputOutputAlias(node1, node2)
+ }
+
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +800,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
- exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +822,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
- TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
+ TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +857,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
- CastingNode() {
- this instanceof ParameterNode or
- this instanceof CastNode or
- this instanceof OutNodeExt or
- // For reads, `x.f`, we want to check that the tracked type after the read (which
- // is obtained by popping the head of the access path stack) is compatible with
- // the type of `x.f`.
- readStep(_, _, this)
- }
+ CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
- readStep(n1, c, n2) and
- container = getNodeType(n1) and
- content = getNodeType(n2)
+ read(n1, c, n2) and
+ container = getNodeDataFlowType(n1) and
+ content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +942,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
+ exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +954,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
- exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
+ exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +987,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
- exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +1001,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/**
+ * The value of a parameter at function entry, viewed as a node in a data
+ * flow graph.
+ */
+class ParameterNodeExt extends Node {
+ ParameterNodeExt() { parameterNode(this, _, _) }
+
+ /**
+ * Holds if this node is the parameter of callable `c` at the specified
+ * (zero-based) position.
+ */
+ predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+}
+
+/** A data-flow node that represents a call argument. */
+class ArgumentNodeExt extends Node {
+ ArgumentNodeExt() { argumentNode(this, _, _) }
+
+ /** Holds if this argument occurs at the given position in the given call. */
+ final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+}
+
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
- ReturnNodeExt() {
- this instanceof ReturnNode or
- parameterValueFlowsToPreUpdate(_, this)
- }
+ ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
- ReturnKindExt getKind() {
- result = TValueReturn(this.(ReturnNode).getKind())
- or
- exists(ParameterNode p, int pos |
- parameterValueFlowsToPreUpdate(p, this) and
- p.isParameterOf(_, pos) and
- result = TParamUpdate(pos)
- )
- }
+ ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1039,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
- OutNodeExt() {
- this instanceof OutNode
- or
- this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
- }
+ OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1052,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
- abstract OutNodeExt getAnOutNode(DataFlowCall call);
+ final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1063,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- result = getAnOutNode(call, this.getKind())
- }
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1073,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- exists(ArgumentNode arg |
- result.(PostUpdateNode).getPreUpdateNode() = arg and
- arg.argumentOf(call, this.getPosition())
- )
- }
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1099,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
- exists(Node n0 |
- pragma[only_bind_into](n0) = n and
- pragma[only_bind_into](result) = n0.getEnclosingCallable()
- )
+ nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
+}
+
+/** Gets the type of `n` used for type pruning. */
+pragma[inline]
+DataFlowType getNodeDataFlowType(Node n) {
+ nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1129,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
- call0.getEnclosingCallable() = callable and
+ callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1150,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
-predicate read = readStep/3;
-
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1201,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
- predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
+ predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll
index a51c20c2288..b5ceabc605d 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll
@@ -35,22 +35,24 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgNonLambda(
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
+ ) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +120,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
- then compatibleTypes(t, getNodeType(node))
+ if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
+ then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +131,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
- t = getNodeType(node) and
+ t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +148,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +162,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
- jumpStep(node, mid) and
+ jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +170,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +178,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,8 +229,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
- DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
+ boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -242,6 +244,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ /**
+ * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
+ * force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
+ * collapsing the two stages.
+ */
+ cached
+ predicate forceCachingInSameStage() { any() }
+
+ cached
+ predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
+
+ cached
+ predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
+ c = call.getEnclosingCallable()
+ }
+
+ cached
+ predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+
+ cached
+ predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+
+ cached
+ predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+
+ cached
+ predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+
+ cached
+ predicate outNodeExt(Node n) {
+ n instanceof OutNode
+ or
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ }
+
+ cached
+ predicate hiddenNode(Node n) { nodeIsHidden(n) }
+
+ cached
+ OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
+ result = getAnOutNode(call, k.(ValueReturnKind).getKind())
+ or
+ exists(ArgumentNodeExt arg |
+ result.(PostUpdateNode).getPreUpdateNode() = arg and
+ arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
+ )
+ }
+
+ cached
+ predicate returnNodeExt(Node n, ReturnKindExt k) {
+ k = TValueReturn(n.(ReturnNode).getKind())
+ or
+ exists(ParameterNodeExt p, int pos |
+ parameterValueFlowsToPreUpdate(p, n) and
+ p.isParameterOf(_, pos) and
+ k = TParamUpdate(pos)
+ )
+ }
+
+ cached
+ predicate castNode(Node n) { n instanceof CastNode }
+
+ cached
+ predicate castingNode(Node n) {
+ castNode(n) or
+ n instanceof ParameterNodeExt or
+ n instanceof OutNodeExt or
+ // For reads, `x.f`, we want to check that the tracked type after the read (which
+ // is obtained by popping the head of the access path stack) is compatible with
+ // the type of `x.f`.
+ read(_, _, n)
+ }
+
+ cached
+ predicate parameterNode(Node n, DataFlowCallable c, int i) {
+ n.(ParameterNode).isParameterOf(c, i)
+ }
+
+ cached
+ predicate argumentNode(Node n, DataFlowCall call, int pos) {
+ n.(ArgumentNode).argumentOf(call, pos)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +346,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +355,11 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
- compatibleTypes(getNodeType(arg), getNodeType(p))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +397,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +410,32 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
- readStep(mid, _, node) and
+ read(mid, _, node) and
read = true
)
or
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
+ private predicate parameterValueFlowArgCand(
+ ParameterNodeExt p, ArgumentNodeExt arg, boolean read
+ ) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +447,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +456,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +469,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNode p, Node n) {
+ predicate cand(ParameterNodeExt p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +503,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(p), getNodeType(node))
+ compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
- compatibleTypes(read.getContentType(), getNodeType(node))
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +534,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
- compatibleTypes(getNodeType(p), read.getContainerType())
+ compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,16 +542,16 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
@@ -472,7 +559,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
+ ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -480,9 +567,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +583,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(arg), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
- compatibleTypes(getNodeType(arg), read.getContainerType()) and
- compatibleTypes(read.getContentType(), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +603,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNode arg, Content c, Node out) {
+ predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +616,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNode p, ReturnKind kind, ReadStepTypesOption read
+ ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +640,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
- callable = call.getEnclosingCallable() and
+ callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +698,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
- tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
+ tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +722,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- cached
- predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +730,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
- readStep(_, c, _) and
- contentType = getNodeType(node1) and
- containerType = getNodeType(node2)
+ read(_, c, _) and
+ contentType = getNodeDataFlowType(node1) and
+ containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +740,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
- readStep(n2, c, n1) and
- contentType = getNodeType(n1) and
- containerType = getNodeType(n2)
+ read(n2, c, n1) and
+ contentType = getNodeDataFlowType(n1) and
+ containerType = getNodeDataFlowType(n2)
)
}
+ cached
+ predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
+
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +767,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
- cached
- predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
+ private predicate reverseStepThroughInputOutputAlias(
+ PostUpdateNode fromNode, PostUpdateNode toNode
+ ) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +778,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNode).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
+ toPre.(ArgumentNodeExt).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
+ cached
+ predicate simpleLocalFlowStepExt(Node node1, Node node2) {
+ simpleLocalFlowStep(node1, node2) or
+ reverseStepThroughInputOutputAlias(node1, node2)
+ }
+
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +800,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
- exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +822,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
- TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
+ TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +857,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
- CastingNode() {
- this instanceof ParameterNode or
- this instanceof CastNode or
- this instanceof OutNodeExt or
- // For reads, `x.f`, we want to check that the tracked type after the read (which
- // is obtained by popping the head of the access path stack) is compatible with
- // the type of `x.f`.
- readStep(_, _, this)
- }
+ CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
- readStep(n1, c, n2) and
- container = getNodeType(n1) and
- content = getNodeType(n2)
+ read(n1, c, n2) and
+ container = getNodeDataFlowType(n1) and
+ content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +942,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
+ exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +954,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
- exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
+ exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +987,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
- exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +1001,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/**
+ * The value of a parameter at function entry, viewed as a node in a data
+ * flow graph.
+ */
+class ParameterNodeExt extends Node {
+ ParameterNodeExt() { parameterNode(this, _, _) }
+
+ /**
+ * Holds if this node is the parameter of callable `c` at the specified
+ * (zero-based) position.
+ */
+ predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+}
+
+/** A data-flow node that represents a call argument. */
+class ArgumentNodeExt extends Node {
+ ArgumentNodeExt() { argumentNode(this, _, _) }
+
+ /** Holds if this argument occurs at the given position in the given call. */
+ final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+}
+
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
- ReturnNodeExt() {
- this instanceof ReturnNode or
- parameterValueFlowsToPreUpdate(_, this)
- }
+ ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
- ReturnKindExt getKind() {
- result = TValueReturn(this.(ReturnNode).getKind())
- or
- exists(ParameterNode p, int pos |
- parameterValueFlowsToPreUpdate(p, this) and
- p.isParameterOf(_, pos) and
- result = TParamUpdate(pos)
- )
- }
+ ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1039,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
- OutNodeExt() {
- this instanceof OutNode
- or
- this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
- }
+ OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1052,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
- abstract OutNodeExt getAnOutNode(DataFlowCall call);
+ final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1063,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- result = getAnOutNode(call, this.getKind())
- }
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1073,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- exists(ArgumentNode arg |
- result.(PostUpdateNode).getPreUpdateNode() = arg and
- arg.argumentOf(call, this.getPosition())
- )
- }
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1099,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
- exists(Node n0 |
- pragma[only_bind_into](n0) = n and
- pragma[only_bind_into](result) = n0.getEnclosingCallable()
- )
+ nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
+}
+
+/** Gets the type of `n` used for type pruning. */
+pragma[inline]
+DataFlowType getNodeDataFlowType(Node n) {
+ nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1129,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
- call0.getEnclosingCallable() = callable and
+ callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1150,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
-predicate read = readStep/3;
-
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1201,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
- predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
+ predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll
index a51c20c2288..b5ceabc605d 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll
@@ -35,22 +35,24 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgNonLambda(
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
+ ) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +120,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
- then compatibleTypes(t, getNodeType(node))
+ if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
+ then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +131,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
- t = getNodeType(node) and
+ t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +148,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +162,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
- jumpStep(node, mid) and
+ jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +170,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +178,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,8 +229,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
- DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
+ boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -242,6 +244,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ /**
+ * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
+ * force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
+ * collapsing the two stages.
+ */
+ cached
+ predicate forceCachingInSameStage() { any() }
+
+ cached
+ predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
+
+ cached
+ predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
+ c = call.getEnclosingCallable()
+ }
+
+ cached
+ predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+
+ cached
+ predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+
+ cached
+ predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+
+ cached
+ predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+
+ cached
+ predicate outNodeExt(Node n) {
+ n instanceof OutNode
+ or
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ }
+
+ cached
+ predicate hiddenNode(Node n) { nodeIsHidden(n) }
+
+ cached
+ OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
+ result = getAnOutNode(call, k.(ValueReturnKind).getKind())
+ or
+ exists(ArgumentNodeExt arg |
+ result.(PostUpdateNode).getPreUpdateNode() = arg and
+ arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
+ )
+ }
+
+ cached
+ predicate returnNodeExt(Node n, ReturnKindExt k) {
+ k = TValueReturn(n.(ReturnNode).getKind())
+ or
+ exists(ParameterNodeExt p, int pos |
+ parameterValueFlowsToPreUpdate(p, n) and
+ p.isParameterOf(_, pos) and
+ k = TParamUpdate(pos)
+ )
+ }
+
+ cached
+ predicate castNode(Node n) { n instanceof CastNode }
+
+ cached
+ predicate castingNode(Node n) {
+ castNode(n) or
+ n instanceof ParameterNodeExt or
+ n instanceof OutNodeExt or
+ // For reads, `x.f`, we want to check that the tracked type after the read (which
+ // is obtained by popping the head of the access path stack) is compatible with
+ // the type of `x.f`.
+ read(_, _, n)
+ }
+
+ cached
+ predicate parameterNode(Node n, DataFlowCallable c, int i) {
+ n.(ParameterNode).isParameterOf(c, i)
+ }
+
+ cached
+ predicate argumentNode(Node n, DataFlowCall call, int pos) {
+ n.(ArgumentNode).argumentOf(call, pos)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +346,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +355,11 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
- compatibleTypes(getNodeType(arg), getNodeType(p))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +397,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +410,32 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
- readStep(mid, _, node) and
+ read(mid, _, node) and
read = true
)
or
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
+ private predicate parameterValueFlowArgCand(
+ ParameterNodeExt p, ArgumentNodeExt arg, boolean read
+ ) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +447,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +456,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +469,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNode p, Node n) {
+ predicate cand(ParameterNodeExt p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +503,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(p), getNodeType(node))
+ compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
- compatibleTypes(read.getContentType(), getNodeType(node))
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +534,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
- compatibleTypes(getNodeType(p), read.getContainerType())
+ compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,16 +542,16 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
@@ -472,7 +559,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
+ ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -480,9 +567,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +583,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(arg), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
- compatibleTypes(getNodeType(arg), read.getContainerType()) and
- compatibleTypes(read.getContentType(), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +603,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNode arg, Content c, Node out) {
+ predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +616,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNode p, ReturnKind kind, ReadStepTypesOption read
+ ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +640,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
- callable = call.getEnclosingCallable() and
+ callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +698,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
- tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
+ tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +722,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- cached
- predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +730,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
- readStep(_, c, _) and
- contentType = getNodeType(node1) and
- containerType = getNodeType(node2)
+ read(_, c, _) and
+ contentType = getNodeDataFlowType(node1) and
+ containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +740,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
- readStep(n2, c, n1) and
- contentType = getNodeType(n1) and
- containerType = getNodeType(n2)
+ read(n2, c, n1) and
+ contentType = getNodeDataFlowType(n1) and
+ containerType = getNodeDataFlowType(n2)
)
}
+ cached
+ predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
+
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +767,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
- cached
- predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
+ private predicate reverseStepThroughInputOutputAlias(
+ PostUpdateNode fromNode, PostUpdateNode toNode
+ ) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +778,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNode).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
+ toPre.(ArgumentNodeExt).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
+ cached
+ predicate simpleLocalFlowStepExt(Node node1, Node node2) {
+ simpleLocalFlowStep(node1, node2) or
+ reverseStepThroughInputOutputAlias(node1, node2)
+ }
+
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +800,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
- exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +822,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
- TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
+ TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +857,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
- CastingNode() {
- this instanceof ParameterNode or
- this instanceof CastNode or
- this instanceof OutNodeExt or
- // For reads, `x.f`, we want to check that the tracked type after the read (which
- // is obtained by popping the head of the access path stack) is compatible with
- // the type of `x.f`.
- readStep(_, _, this)
- }
+ CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
- readStep(n1, c, n2) and
- container = getNodeType(n1) and
- content = getNodeType(n2)
+ read(n1, c, n2) and
+ container = getNodeDataFlowType(n1) and
+ content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +942,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
+ exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +954,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
- exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
+ exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +987,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
- exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +1001,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/**
+ * The value of a parameter at function entry, viewed as a node in a data
+ * flow graph.
+ */
+class ParameterNodeExt extends Node {
+ ParameterNodeExt() { parameterNode(this, _, _) }
+
+ /**
+ * Holds if this node is the parameter of callable `c` at the specified
+ * (zero-based) position.
+ */
+ predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+}
+
+/** A data-flow node that represents a call argument. */
+class ArgumentNodeExt extends Node {
+ ArgumentNodeExt() { argumentNode(this, _, _) }
+
+ /** Holds if this argument occurs at the given position in the given call. */
+ final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+}
+
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
- ReturnNodeExt() {
- this instanceof ReturnNode or
- parameterValueFlowsToPreUpdate(_, this)
- }
+ ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
- ReturnKindExt getKind() {
- result = TValueReturn(this.(ReturnNode).getKind())
- or
- exists(ParameterNode p, int pos |
- parameterValueFlowsToPreUpdate(p, this) and
- p.isParameterOf(_, pos) and
- result = TParamUpdate(pos)
- )
- }
+ ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1039,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
- OutNodeExt() {
- this instanceof OutNode
- or
- this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
- }
+ OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1052,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
- abstract OutNodeExt getAnOutNode(DataFlowCall call);
+ final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1063,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- result = getAnOutNode(call, this.getKind())
- }
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1073,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- exists(ArgumentNode arg |
- result.(PostUpdateNode).getPreUpdateNode() = arg and
- arg.argumentOf(call, this.getPosition())
- )
- }
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1099,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
- exists(Node n0 |
- pragma[only_bind_into](n0) = n and
- pragma[only_bind_into](result) = n0.getEnclosingCallable()
- )
+ nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
+}
+
+/** Gets the type of `n` used for type pruning. */
+pragma[inline]
+DataFlowType getNodeDataFlowType(Node n) {
+ nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1129,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
- call0.getEnclosingCallable() = callable and
+ callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1150,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
-predicate read = readStep/3;
-
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1201,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
- predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
+ predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll
index 9498e51e7e6..cf83530bcbd 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll
@@ -211,10 +211,7 @@ private predicate fullBarrier(Node node, Configuration config) {
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStep(Node node1, Node node2, Configuration config) {
- (
- simpleLocalFlowStep(node1, node2) or
- reverseStepThroughInputOutputAlias(node1, node2)
- ) and
+ simpleLocalFlowStepExt(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -237,7 +234,7 @@ private predicate additionalLocalFlowStep(Node node1, Node node2, Configuration
* Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
*/
private predicate jumpStep(Node node1, Node node2, Configuration config) {
- jumpStep(node1, node2) and
+ jumpStepCached(node1, node2) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
@@ -388,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -515,7 +512,7 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
@@ -523,16 +520,16 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNode arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -597,7 +594,9 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -663,7 +662,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNode p, ArgumentNode arg, Configuration config
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -675,7 +674,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -735,7 +734,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNode arg, ParameterNode p, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
@@ -944,10 +943,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -992,7 +991,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1133,10 +1132,10 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1146,7 +1145,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1199,13 +1198,15 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1245,7 +1246,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
@@ -1260,8 +1261,8 @@ private module LocalFlowBigStep {
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
- this instanceof CastNode or
- clearsContent(this, _)
+ castNode(this) or
+ clearsContentCached(this, _)
}
}
@@ -1275,7 +1276,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNode or
+ node instanceof ParameterNodeExt or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1321,21 +1322,21 @@ private module LocalFlowBigStep {
Node node1, Node node2, boolean preservesValue, DataFlowType t, Configuration config,
LocalCallContext cc
) {
- not isUnreachableInCall(node2, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node2, cc.(LocalCallContextSpecificCall).getCall()) and
(
localFlowEntry(node1, pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
- t = getNodeType(node1)
+ t = getNodeDataFlowType(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
- t = getNodeType(node2)
+ t = getNodeDataFlowType(node2)
) and
node1 != node2 and
cc.relevantFor(getNodeEnclosingCallable(node1)) and
- not isUnreachableInCall(node1, cc.(LocalCallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node1, cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
or
exists(Node mid |
@@ -1350,7 +1351,7 @@ private module LocalFlowBigStep {
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
- t = getNodeType(node2) and
+ t = getNodeDataFlowType(node2) and
Stage2::revFlow(node2, pragma[only_bind_into](config))
)
)
@@ -1384,7 +1385,7 @@ private module Stage3 {
private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TFrontNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TFrontNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -1443,7 +1444,9 @@ private module Stage3 {
bindingset[node, ap]
private predicate filter(Node node, Ap ap) {
not ap.isClearedAt(node) and
- if node instanceof CastingNode then compatibleTypes(getNodeType(node), ap.getType()) else any()
+ if node instanceof CastingNode
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
+ else any()
}
bindingset[ap, contentType]
@@ -1583,10 +1586,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1631,7 +1634,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1772,10 +1775,10 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1785,7 +1788,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1838,13 +1841,15 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2088,7 +2093,7 @@ private module Stage4 {
private ApApprox getApprox(Ap ap) { result = ap.getFront() }
private ApNil getApNil(Node node) {
- PrevStage::revFlow(node, _) and result = TNil(getNodeType(node))
+ PrevStage::revFlow(node, _) and result = TNil(getNodeDataFlowType(node))
}
bindingset[tc, tail]
@@ -2155,7 +2160,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNode node1, ParameterNode node2, boolean allowsFieldFlow,
+ DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
@@ -2300,10 +2305,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNode arg, boolean allowsFieldFlow |
+ exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2348,7 +2353,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2489,10 +2494,10 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNode arg, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
- exists(ParameterNode p, boolean allowsFieldFlow |
+ exists(ParameterNodeExt p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2502,7 +2507,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNode arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2555,13 +2560,15 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, Ap ap, Configuration config) {
+ predicate parameterMayFlowThrough(
+ ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
+ ) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2606,7 +2613,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNode p, AccessPath ap) {
+ TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2627,7 +2634,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNode p;
+ private ParameterNodeExt p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -2758,7 +2765,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2979,7 +2986,7 @@ class PathNode extends TPathNode {
Configuration getConfiguration() { none() }
private predicate isHidden() {
- nodeIsHidden(this.getNode()) and
+ hiddenNode(this.getNode()) and
not this.isSource() and
not this instanceof PathNodeSink
}
@@ -3148,7 +3155,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
- ap = TAccessPathNil(getNodeType(node))
+ ap = TAccessPathNil(getNodeDataFlowType(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -3235,7 +3242,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3248,7 +3255,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3272,7 +3279,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3568,7 +3575,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNode p)
+ TSummaryCtx1Param(ParameterNodeExt p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3591,7 +3598,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -3611,7 +3618,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
- not clearsContent(node, ap.getHead()) and
+ not clearsContentCached(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(getNodeEnclosingCallable(node), config) <= config.explorationLimit()
)
@@ -3625,9 +3632,9 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
- not clearsContent(node, ap.getHead().getContent()) and
+ not clearsContentCached(node, ap.getHead().getContent()) and
if node instanceof CastingNode
- then compatibleTypes(getNodeType(node), ap.getType())
+ then compatibleTypes(getNodeDataFlowType(node), ap.getType())
else any()
)
}
@@ -3783,7 +3790,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, Node node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
PartialAccessPath ap, Configuration config
) {
- not isUnreachableInCall(node, cc.(CallContextSpecificCall).getCall()) and
+ not isUnreachableInCallCached(node, cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNode(), node, config) and
cc = mid.getCallContext() and
@@ -3797,7 +3804,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
)
or
@@ -3813,7 +3820,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
- ap = TPartialNil(getNodeType(node)) and
+ ap = TPartialNil(getNodeDataFlowType(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -3827,7 +3834,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
- compatibleTypes(ap.getType(), getNodeType(node))
+ compatibleTypes(ap.getType(), getNodeDataFlowType(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
@@ -3924,7 +3931,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3943,7 +3950,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3980,7 +3987,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4037,7 +4044,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNode p |
+ exists(ParameterNodeExt p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4115,7 +4122,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNode p |
+ exists(PartialPathNodeRev mid, ParameterNodeExt p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4138,7 +4145,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNode node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll
index a51c20c2288..b5ceabc605d 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll
@@ -35,22 +35,24 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgNonLambda(
+ DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
+ ) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -118,8 +120,8 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and
- if node instanceof CastNode or node instanceof ArgumentNode or node instanceof ReturnNode
- then compatibleTypes(t, getNodeType(node))
+ if castNode(node) or node instanceof ArgumentNodeExt or node instanceof ReturnNode
+ then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -129,7 +131,7 @@ private module LambdaFlow {
boolean toJump, DataFlowCallOption lastCall
) {
lambdaCall(lambdaCall, kind, node) and
- t = getNodeType(node) and
+ t = getNodeDataFlowType(node) and
toReturn = false and
toJump = false and
lastCall = TDataFlowCallNone()
@@ -146,7 +148,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -160,7 +162,7 @@ private module LambdaFlow {
toJump = true and
lastCall = TDataFlowCallNone()
|
- jumpStep(node, mid) and
+ jumpStepCached(node, mid) and
t = t0
or
exists(boolean preservesValue |
@@ -168,7 +170,7 @@ private module LambdaFlow {
getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid)
|
preservesValue = false and
- t = getNodeType(node)
+ t = getNodeDataFlowType(node)
or
preservesValue = true and
t = t0
@@ -176,7 +178,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNode p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -227,8 +229,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNode p, DataFlowType t, boolean toJump,
- DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
+ boolean toJump, DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -242,6 +244,89 @@ private DataFlowCallable viableCallableExt(DataFlowCall call) {
cached
private module Cached {
+ /**
+ * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to
+ * force a stage-dependency on the `DataFlowImplCommon.qll` stage and therby
+ * collapsing the two stages.
+ */
+ cached
+ predicate forceCachingInSameStage() { any() }
+
+ cached
+ predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
+
+ cached
+ predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
+ c = call.getEnclosingCallable()
+ }
+
+ cached
+ predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) }
+
+ cached
+ predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
+
+ cached
+ predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
+
+ cached
+ predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
+
+ cached
+ predicate outNodeExt(Node n) {
+ n instanceof OutNode
+ or
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ }
+
+ cached
+ predicate hiddenNode(Node n) { nodeIsHidden(n) }
+
+ cached
+ OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
+ result = getAnOutNode(call, k.(ValueReturnKind).getKind())
+ or
+ exists(ArgumentNodeExt arg |
+ result.(PostUpdateNode).getPreUpdateNode() = arg and
+ arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
+ )
+ }
+
+ cached
+ predicate returnNodeExt(Node n, ReturnKindExt k) {
+ k = TValueReturn(n.(ReturnNode).getKind())
+ or
+ exists(ParameterNodeExt p, int pos |
+ parameterValueFlowsToPreUpdate(p, n) and
+ p.isParameterOf(_, pos) and
+ k = TParamUpdate(pos)
+ )
+ }
+
+ cached
+ predicate castNode(Node n) { n instanceof CastNode }
+
+ cached
+ predicate castingNode(Node n) {
+ castNode(n) or
+ n instanceof ParameterNodeExt or
+ n instanceof OutNodeExt or
+ // For reads, `x.f`, we want to check that the tracked type after the read (which
+ // is obtained by popping the head of the access path stack) is compatible with
+ // the type of `x.f`.
+ read(_, _, n)
+ }
+
+ cached
+ predicate parameterNode(Node n, DataFlowCallable c, int i) {
+ n.(ParameterNode).isParameterOf(c, i)
+ }
+
+ cached
+ predicate argumentNode(Node n, DataFlowCall call, int pos) {
+ n.(ArgumentNode).argumentOf(call, pos)
+ }
+
/**
* Gets a viable target for the lambda call `call`.
*
@@ -261,7 +346,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNode p) {
+ private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -270,11 +355,11 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
+ predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
- compatibleTypes(getNodeType(arg), getNodeType(p))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
)
}
@@ -312,7 +397,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
p = node and
read = false
or
@@ -325,30 +410,32 @@ private module Cached {
// read
exists(Node mid |
parameterValueFlowCand(p, mid, false) and
- readStep(mid, _, node) and
+ read(mid, _, node) and
read = true
)
or
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
+ private predicate parameterValueFlowArgCand(
+ ParameterNodeExt p, ArgumentNodeExt arg, boolean read
+ ) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -360,7 +447,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -369,9 +456,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -382,14 +469,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNode p, Node n) {
+ predicate cand(ParameterNodeExt p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -416,21 +503,21 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNode p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(p), getNodeType(node))
+ compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node))
or
// getter
- compatibleTypes(read.getContentType(), getNodeType(node))
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(node))
else any()
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNode p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -447,7 +534,7 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
- compatibleTypes(getNodeType(p), read.getContainerType())
+ compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
@@ -455,16 +542,16 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNode arg |
+ exists(ArgumentNodeExt arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
@@ -472,7 +559,7 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlowArg(
- ParameterNode p, ArgumentNode arg, ReadStepTypesOption read
+ ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
@@ -480,9 +567,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNode arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNode param | viableParamArg(call, param, arg) |
+ exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -496,18 +583,18 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNode arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
|
// normal flow through
read = TReadStepTypesNone() and
- compatibleTypes(getNodeType(arg), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out))
or
// getter
- compatibleTypes(getNodeType(arg), read.getContainerType()) and
- compatibleTypes(read.getContentType(), getNodeType(out))
+ compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and
+ compatibleTypes(read.getContentType(), getNodeDataFlowType(out))
)
}
@@ -516,7 +603,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNode arg, Content c, Node out) {
+ predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -529,7 +616,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNode p, ReturnKind kind, ReadStepTypesOption read
+ ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -553,7 +640,7 @@ private module Cached {
private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) {
mayBenefitFromCallContext(call, callable)
or
- callable = call.getEnclosingCallable() and
+ callEnclosingCallable(call, callable) and
exists(viableCallableLambda(call, TDataFlowCallSome(_)))
}
@@ -611,7 +698,7 @@ private module Cached {
mayBenefitFromCallContextExt(call, _) and
c = viableCallableExt(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and
- tgts = strictcount(DataFlowCall ctx | viableCallableExt(ctx) = call.getEnclosingCallable()) and
+ tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and
ctxtgts < tgts
)
}
@@ -635,8 +722,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- cached
- predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -644,9 +730,9 @@ private module Cached {
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
) {
storeStep(node1, c, node2) and
- readStep(_, c, _) and
- contentType = getNodeType(node1) and
- containerType = getNodeType(node2)
+ read(_, c, _) and
+ contentType = getNodeDataFlowType(node1) and
+ containerType = getNodeDataFlowType(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -654,12 +740,15 @@ private module Cached {
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
- readStep(n2, c, n1) and
- contentType = getNodeType(n1) and
- containerType = getNodeType(n2)
+ read(n2, c, n1) and
+ contentType = getNodeDataFlowType(n1) and
+ containerType = getNodeDataFlowType(n2)
)
}
+ cached
+ predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
+
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f`.
@@ -678,8 +767,9 @@ private module Cached {
* are aliases. A typical example is a function returning `this`, implementing a fluent
* interface.
*/
- cached
- predicate reverseStepThroughInputOutputAlias(PostUpdateNode fromNode, PostUpdateNode toNode) {
+ private predicate reverseStepThroughInputOutputAlias(
+ PostUpdateNode fromNode, PostUpdateNode toNode
+ ) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
toPre = toNode.getPreUpdateNode()
@@ -688,14 +778,20 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNode).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNode), fromPre)
+ toPre.(ArgumentNodeExt).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
)
}
+ cached
+ predicate simpleLocalFlowStepExt(Node node1, Node node2) {
+ simpleLocalFlowStep(node1, node2) or
+ reverseStepThroughInputOutputAlias(node1, node2)
+ }
+
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -704,7 +800,7 @@ private module Cached {
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
reducedViableImplInCallContext(_, callable, call)
or
- exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
}
cached
@@ -726,12 +822,12 @@ private module Cached {
cached
newtype TLocalFlowCallContext =
TAnyLocalCall() or
- TSpecificLocalCall(DataFlowCall call) { isUnreachableInCall(_, call) }
+ TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) }
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -761,23 +857,15 @@ private module Cached {
* A `Node` at which a cast can occur such that the type should be checked.
*/
class CastingNode extends Node {
- CastingNode() {
- this instanceof ParameterNode or
- this instanceof CastNode or
- this instanceof OutNodeExt or
- // For reads, `x.f`, we want to check that the tracked type after the read (which
- // is obtained by popping the head of the access path stack) is compatible with
- // the type of `x.f`.
- readStep(_, _, this)
- }
+ CastingNode() { castingNode(this) }
}
private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
- readStep(n1, c, n2) and
- container = getNodeType(n1) and
- content = getNodeType(n2)
+ read(n1, c, n2) and
+ container = getNodeDataFlowType(n1) and
+ content = getNodeDataFlowType(n2)
}
private newtype TReadStepTypesOption =
@@ -854,7 +942,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNode p | getNodeEnclosingCallable(p) = callable)
+ exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -866,7 +954,7 @@ class CallContextReturn extends CallContextNoCall, TReturn {
}
override predicate relevantFor(DataFlowCallable callable) {
- exists(DataFlowCall call | this = TReturn(_, call) and call.getEnclosingCallable() = callable)
+ exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable))
}
}
@@ -899,7 +987,7 @@ class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall
}
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
- exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCall(n, call))
+ exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
}
/**
@@ -913,26 +1001,37 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
else result instanceof LocalCallContextAny
}
+/**
+ * The value of a parameter at function entry, viewed as a node in a data
+ * flow graph.
+ */
+class ParameterNodeExt extends Node {
+ ParameterNodeExt() { parameterNode(this, _, _) }
+
+ /**
+ * Holds if this node is the parameter of callable `c` at the specified
+ * (zero-based) position.
+ */
+ predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+}
+
+/** A data-flow node that represents a call argument. */
+class ArgumentNodeExt extends Node {
+ ArgumentNodeExt() { argumentNode(this, _, _) }
+
+ /** Holds if this argument occurs at the given position in the given call. */
+ final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+}
+
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
class ReturnNodeExt extends Node {
- ReturnNodeExt() {
- this instanceof ReturnNode or
- parameterValueFlowsToPreUpdate(_, this)
- }
+ ReturnNodeExt() { returnNodeExt(this, _) }
/** Gets the kind of this returned value. */
- ReturnKindExt getKind() {
- result = TValueReturn(this.(ReturnNode).getKind())
- or
- exists(ParameterNode p, int pos |
- parameterValueFlowsToPreUpdate(p, this) and
- p.isParameterOf(_, pos) and
- result = TParamUpdate(pos)
- )
- }
+ ReturnKindExt getKind() { returnNodeExt(this, result) }
}
/**
@@ -940,11 +1039,7 @@ class ReturnNodeExt extends Node {
* or a post-update node associated with a call argument.
*/
class OutNodeExt extends Node {
- OutNodeExt() {
- this instanceof OutNode
- or
- this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
- }
+ OutNodeExt() { outNodeExt(this) }
}
/**
@@ -957,7 +1052,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
abstract string toString();
/** Gets a node corresponding to data flow out of `call`. */
- abstract OutNodeExt getAnOutNode(DataFlowCall call);
+ final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) }
}
class ValueReturnKind extends ReturnKindExt, TValueReturn {
@@ -968,10 +1063,6 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
ReturnKind getKind() { result = kind }
override string toString() { result = kind.toString() }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- result = getAnOutNode(call, this.getKind())
- }
}
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
@@ -982,13 +1073,6 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
int getPosition() { result = pos }
override string toString() { result = "param update " + pos }
-
- override OutNodeExt getAnOutNode(DataFlowCall call) {
- exists(ArgumentNode arg |
- result.(PostUpdateNode).getPreUpdateNode() = arg and
- arg.argumentOf(call, this.getPosition())
- )
- }
}
/** A callable tagged with a relevant return kind. */
@@ -1015,10 +1099,13 @@ class ReturnPosition extends TReturnPosition0 {
*/
pragma[inline]
DataFlowCallable getNodeEnclosingCallable(Node n) {
- exists(Node n0 |
- pragma[only_bind_into](n0) = n and
- pragma[only_bind_into](result) = n0.getEnclosingCallable()
- )
+ nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result))
+}
+
+/** Gets the type of `n` used for type pruning. */
+pragma[inline]
+DataFlowType getNodeDataFlowType(Node n) {
+ nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result))
}
pragma[noinline]
@@ -1042,7 +1129,7 @@ predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall
cc instanceof CallContextAny and callable = viableCallableExt(call)
or
exists(DataFlowCallable c0, DataFlowCall call0 |
- call0.getEnclosingCallable() = callable and
+ callEnclosingCallable(call0, callable) and
cc = TReturn(c0, call0) and
c0 = prunedViableImplInCallContextReverse(call0, call)
)
@@ -1063,8 +1150,6 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallableExt(call) and cc instanceof CallContextReturn
}
-predicate read = readStep/3;
-
/** An optional Boolean value. */
class BooleanOption extends TBooleanOption {
string toString() {
@@ -1116,7 +1201,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
- predicate isClearedAt(Node n) { clearsContent(n, getHead().getContent()) }
+ predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
From befc80b3cbe8ac7899a2e5b023ba2a39d5221099 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 17:02:28 +0200
Subject: [PATCH 114/550] C#: Update data-flow caching
---
csharp/ql/src/semmle/code/csharp/Caching.qll | 38 --
.../dataflow/internal/DataFlowDispatch.qll | 49 +-
.../dataflow/internal/DataFlowPrivate.qll | 582 ++++++++----------
.../dataflow/internal/DataFlowPublic.qll | 12 +-
.../internal/TaintTrackingPrivate.qll | 7 +-
5 files changed, 304 insertions(+), 384 deletions(-)
diff --git a/csharp/ql/src/semmle/code/csharp/Caching.qll b/csharp/ql/src/semmle/code/csharp/Caching.qll
index 374ecaaa183..92417e34586 100644
--- a/csharp/ql/src/semmle/code/csharp/Caching.qll
+++ b/csharp/ql/src/semmle/code/csharp/Caching.qll
@@ -47,44 +47,6 @@ module Stages {
}
}
- cached
- module DataFlowStage {
- private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
- private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
- private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
- private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate
-
- cached
- predicate forceCachingInSameStage() { any() }
-
- cached
- private predicate forceCachingInSameStageRev() {
- defaultAdditionalTaintStep(_, _)
- or
- any(ArgumentNode n).argumentOf(_, _)
- or
- exists(any(DataFlow::Node n).getEnclosingCallable())
- or
- exists(any(DataFlow::Node n).getControlFlowNode())
- or
- exists(any(DataFlow::Node n).getType())
- or
- exists(any(NodeImpl n).getDataFlowType())
- or
- exists(any(DataFlow::Node n).getLocation())
- or
- exists(any(DataFlow::Node n).toString())
- or
- exists(any(OutNode n).getCall(_))
- or
- exists(CallContext cc)
- or
- exists(any(DataFlowCall c).getEnclosingCallable())
- or
- forceCachingInSameStageRev()
- }
- }
-
cached
module UnificationStage {
private import semmle.code.csharp.Unification
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll
index 0a7cf4acc41..04465f5ae9e 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll
@@ -1,10 +1,10 @@
private import csharp
private import cil
private import dotnet
+private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPublic
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
-private import semmle.code.csharp.Caching
private import semmle.code.csharp.dataflow.FlowSummary
private import semmle.code.csharp.dispatch.Dispatch
private import semmle.code.csharp.frameworks.system.Collections
@@ -68,31 +68,30 @@ private predicate transitiveCapturedCallTarget(ControlFlow::Nodes::ElementNode c
)
}
-cached
-private module Cached {
- cached
- newtype TReturnKind =
- TNormalReturnKind() { Stages::DataFlowStage::forceCachingInSameStage() } or
- TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
- TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
- TImplicitCapturedReturnKind(LocalScopeVariable v) {
- exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
- v = def.getSourceVariable().getAssignable()
- )
- } or
- TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
- rk instanceof NormalReturnKind and
- (
- target instanceof Constructor or
- not target.getReturnType() instanceof VoidType
- )
- or
- exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
- }
+newtype TReturnKind =
+ TNormalReturnKind() or
+ TOutReturnKind(int i) { i = any(Parameter p | p.isOut()).getPosition() } or
+ TRefReturnKind(int i) { i = any(Parameter p | p.isRef()).getPosition() } or
+ TImplicitCapturedReturnKind(LocalScopeVariable v) {
+ exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowOut(_, _) |
+ v = def.getSourceVariable().getAssignable()
+ )
+ } or
+ TJumpReturnKind(DataFlowCallable target, ReturnKind rk) {
+ rk instanceof NormalReturnKind and
+ (
+ target instanceof Constructor or
+ not target.getReturnType() instanceof VoidType
+ )
+ or
+ exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
+ }
+private module Cached {
cached
newtype TDataFlowCall =
TNonDelegateCall(ControlFlow::Nodes::ElementNode cfn, DispatchCall dc) {
+ DataFlowImplCommon::forceCachingInSameStage() and
cfn.getElement() = dc.getCall()
} or
TExplicitDelegateLikeCall(ControlFlow::Nodes::ElementNode cfn, DelegateLikeCall dc) {
@@ -246,7 +245,6 @@ abstract class DataFlowCall extends TDataFlowCall {
abstract DataFlow::Node getNode();
/** Gets the enclosing callable of this call. */
- cached
abstract DataFlowCallable getEnclosingCallable();
/** Gets the underlying expression, if any. */
@@ -280,10 +278,7 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
override DataFlow::ExprNode getNode() { result.getControlFlowNode() = cfn }
- override DataFlowCallable getEnclosingCallable() {
- Stages::DataFlowStage::forceCachingInSameStage() and
- result = cfn.getEnclosingCallable()
- }
+ override DataFlowCallable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
override string toString() { result = cfn.toString() }
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll
index f42410ca3a5..c1b15df72dc 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll
@@ -7,7 +7,6 @@ private import DataFlowImplCommon
private import ControlFlowReachability
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.FlowSummary
-private import semmle.code.csharp.Caching
private import semmle.code.csharp.Conversion
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
private import semmle.code.csharp.ExprOrStmtParent
@@ -21,7 +20,6 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
abstract class NodeImpl extends Node {
/** Do not call: use `getEnclosingCallable()` instead. */
- cached
abstract DataFlowCallable getEnclosingCallableImpl();
/** Do not call: use `getType()` instead. */
@@ -29,9 +27,8 @@ abstract class NodeImpl extends Node {
abstract DotNet::Type getTypeImpl();
/** Gets the type of this node used for type pruning. */
- cached
Gvn::GvnType getDataFlowType() {
- Stages::DataFlowStage::forceCachingInSameStage() and
+ forceCachingInSameStage() and
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
t0 = getCSharpType(this.getType())
or
@@ -55,26 +52,25 @@ abstract class NodeImpl extends Node {
private class ExprNodeImpl extends ExprNode, NodeImpl {
override DataFlowCallable getEnclosingCallableImpl() {
- Stages::DataFlowStage::forceCachingInSameStage() and
result = this.getExpr().getEnclosingCallable()
}
override DotNet::Type getTypeImpl() {
- Stages::DataFlowStage::forceCachingInSameStage() and
+ forceCachingInSameStage() and
result = this.getExpr().getType()
}
override ControlFlow::Nodes::ElementNode getControlFlowNodeImpl() {
- Stages::DataFlowStage::forceCachingInSameStage() and this = TExprNode(result)
+ forceCachingInSameStage() and this = TExprNode(result)
}
override Location getLocationImpl() {
- Stages::DataFlowStage::forceCachingInSameStage() and result = this.getExpr().getLocation()
+ forceCachingInSameStage() and result = this.getExpr().getLocation()
}
override string toStringImpl() {
- Stages::DataFlowStage::forceCachingInSameStage() and
- result = this.getControlFlowNode().toString()
+ forceCachingInSameStage() and
+ result = this.getControlFlowNodeImpl().toString()
or
exists(CIL::Expr e |
this = TCilExprNode(e) and
@@ -394,6 +390,22 @@ module LocalFlow {
}
}
+/**
+ * This is the local flow predicate that is used as a building block in global
+ * data flow. It excludes SSA flow through instance fields, as flow through fields
+ * is handled by the global data-flow library, but includes various other steps
+ * that are only relevant for global flow.
+ */
+predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
+ LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
+ or
+ LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
+ or
+ FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
+ or
+ nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
+}
+
pragma[noinline]
private Expr getImplicitArgument(Call c, int pos) {
result = c.getArgument(pos) and
@@ -582,12 +594,16 @@ private Type getCSharpType(DotNet::Type t) {
result.matchesHandle(t)
}
+private class RelevantDataFlowType extends DataFlowType {
+ RelevantDataFlowType() { this = any(NodeImpl n).getDataFlowType() }
+}
+
/** A GVN type that is either a `DataFlowType` or unifiable with a `DataFlowType`. */
private class DataFlowTypeOrUnifiable extends Gvn::GvnType {
pragma[nomagic]
DataFlowTypeOrUnifiable() {
- this instanceof DataFlowType or
- Gvn::unifiable(any(DataFlowType t), this)
+ this instanceof RelevantDataFlowType or
+ Gvn::unifiable(any(RelevantDataFlowType t), this)
}
}
@@ -598,7 +614,7 @@ private TypeParameter getATypeParameterSubType(DataFlowTypeOrUnifiable t) {
}
pragma[noinline]
-private TypeParameter getATypeParameterSubTypeRestricted(DataFlowType t) {
+private TypeParameter getATypeParameterSubTypeRestricted(RelevantDataFlowType t) {
result = getATypeParameterSubType(t)
}
@@ -614,17 +630,30 @@ private Gvn::GvnType getANonTypeParameterSubType(DataFlowTypeOrUnifiable t) {
}
pragma[noinline]
-private Gvn::GvnType getANonTypeParameterSubTypeRestricted(DataFlowType t) {
+private Gvn::GvnType getANonTypeParameterSubTypeRestricted(RelevantDataFlowType t) {
result = getANonTypeParameterSubType(t)
}
/** A collection of cached types and predicates to be evaluated in the same stage. */
cached
private module Cached {
+ private import TaintTrackingPrivate as TaintTrackingPrivate
+
+ // Add artificial dependencies to enforce all cached predicates are evaluated
+ // in the "DataFlowImplCommon stage"
+ private predicate forceCaching() {
+ TaintTrackingPrivate::forceCachingInSameStage() or
+ exists(any(NodeImpl n).getTypeImpl()) or
+ exists(any(NodeImpl n).getControlFlowNodeImpl()) or
+ exists(any(NodeImpl n).getLocationImpl()) or
+ exists(any(NodeImpl n).toStringImpl())
+ }
+
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
- Stages::DataFlowStage::forceCachingInSameStage() and cfn.getElement() instanceof Expr
+ forceCaching() and
+ cfn.getElement() instanceof Expr
} or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TSsaDefinitionNode(Ssa::Definition def) {
@@ -679,23 +708,6 @@ private module Cached {
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
}
- /**
- * This is the local flow predicate that is used as a building block in global
- * data flow. It excludes SSA flow through instance fields, as flow through fields
- * is handled by the global data-flow library, but includes various other steps
- * that are only relevant for global flow.
- */
- cached
- predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
- LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
- or
- LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
- or
- FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
- or
- nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
- }
-
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
@@ -714,178 +726,14 @@ private module Cached {
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
}
- /**
- * Holds if `pred` can flow to `succ`, by jumping from one callable to
- * another. Additional steps specified by the configuration are *not*
- * taken into account.
- */
- cached
- predicate jumpStepImpl(Node pred, Node succ) {
- pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
- or
- exists(FieldOrProperty fl, FieldOrPropertyRead flr |
- fl.isStatic() and
- fl.isFieldLike() and
- fl.getAnAssignedValue() = pred.asExpr() and
- fl.getAnAccess() = flr and
- flr = succ.asExpr() and
- flr.hasNonlocalValue()
- )
- or
- exists(JumpReturnKind jrk, DataFlowCall call |
- FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
- viableCallable(call) = jrk.getTarget() and
- succ = getAnOutNode(call, jrk.getTargetReturnKind())
- )
- }
-
cached
newtype TContent =
TFieldContent(Field f) { f.isUnboundDeclaration() } or
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
TElementContent()
- /**
- * Holds if data can flow from `node1` to `node2` via an assignment to
- * content `c`.
- */
- cached
- predicate storeStepImpl(Node node1, Content c, Node node2) {
- exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
- hasNodePath(x, node1, node) and
- if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
- |
- fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
- or
- arrayStore(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
- )
- or
- exists(StoreStepConfiguration x, Expr arg, ControlFlow::Node callCfn |
- x.hasExprPath(arg, node1.(ExprNode).getControlFlowNode(), _, callCfn) and
- node2 = TParamsArgumentNode(callCfn) and
- isParamsArg(_, arg, _) and
- c instanceof ElementContent
- )
- or
- exists(Expr e |
- e = node1.asExpr() and
- node2.(YieldReturnNode).getYieldReturnStmt().getExpr() = e and
- c instanceof ElementContent
- )
- or
- exists(Expr e |
- e = node1.asExpr() and
- node2.(AsyncReturnNode).getExpr() = e and
- c = getResultContent()
- )
- or
- FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
- }
-
pragma[nomagic]
- private PropertyContent getResultContent() {
- result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty()
- }
-
- /**
- * Holds if data can flow from `node1` to `node2` via a read of content `c`.
- */
- cached
- predicate readStepImpl(Node node1, Content c, Node node2) {
- exists(ReadStepConfiguration x |
- hasNodePath(x, node1, node2) and
- fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
- or
- hasNodePath(x, node1, node2) and
- arrayRead(node1.asExpr(), node2.asExpr()) and
- c instanceof ElementContent
- or
- exists(ForeachStmt fs, Ssa::ExplicitDefinition def |
- x.hasDefPath(fs.getIterableExpr(), node1.getControlFlowNode(), def.getADefinition(),
- def.getControlFlowNode()) and
- node2.(SsaDefinitionNode).getDefinition() = def and
- c instanceof ElementContent
- )
- or
- hasNodePath(x, node1, node2) and
- node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
- c = getResultContent()
- or
- // node1 = (..., node2, ...)
- // node1.ItemX flows to node2
- exists(TupleExpr te, int i, Expr item |
- te = node1.asExpr() and
- not te.isConstruction() and
- c.(FieldContent).getField() = te.getType().(TupleType).getElement(i).getUnboundDeclaration() and
- // node1 = (..., item, ...)
- te.getArgument(i) = item
- |
- // item = (..., ..., ...) in node1 = (..., (..., ..., ...), ...)
- node2.asExpr().(TupleExpr) = item and
- hasNodePath(x, node1, node2)
- or
- // item = variable in node1 = (..., variable, ...)
- exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
- node2.(SsaDefinitionNode).getDefinition() = def and
- def.getADefinition() = tad and
- tad.getLeaf() = item and
- hasNodePath(x, node1, node2)
- )
- or
- // item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
- te = any(PatternExpr pe).getAChildExpr*() and
- exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
- node2.(SsaDefinitionNode).getDefinition() = def and
- def.getADefinition() = lvd and
- lvd.getDeclaration() = item and
- hasNodePath(x, node1, node2)
- )
- )
- )
- or
- FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
- }
-
- /**
- * Holds if values stored inside content `c` are cleared at node `n`. For example,
- * any value stored inside `f` is cleared at the pre-update node associated with `x`
- * in `x.f = newValue`.
- */
- cached
- predicate clearsContent(Node n, Content c) {
- fieldOrPropertyStore(_, c, _, n.asExpr(), true)
- or
- fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
- or
- FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) and
- not c instanceof ElementContent
- or
- FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
- or
- exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
- oi = we.getInitializer() and
- n.asExpr() = oi and
- f = oi.getAMemberInitializer().getInitializedMember() and
- c = f.getContent()
- )
- }
-
- /**
- * Holds if the node `n` is unreachable when the call context is `call`.
- */
- cached
- predicate isUnreachableInCall(Node n, DataFlowCall call) {
- exists(
- ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
- |
- viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
- paramNode.getSsaDefinition().getARead() = guard and
- guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
- )
- }
-
- pragma[nomagic]
- private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, DataFlowType t2) {
+ private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, RelevantDataFlowType t2) {
not t1 instanceof Gvn::TypeParameterGvnType and
t1 = t2
or
@@ -899,102 +747,53 @@ private module Cached {
* `t2` are allowed to be type parameters.
*/
cached
- predicate commonSubType(DataFlowType t1, DataFlowType t2) { commonSubTypeGeneral(t1, t2) }
+ predicate commonSubType(RelevantDataFlowType t1, RelevantDataFlowType t2) {
+ commonSubTypeGeneral(t1, t2)
+ }
cached
- predicate commonSubTypeUnifiableLeft(DataFlowType t1, DataFlowType t2) {
+ predicate commonSubTypeUnifiableLeft(RelevantDataFlowType t1, RelevantDataFlowType t2) {
exists(Gvn::GvnType t |
Gvn::unifiable(t1, t) and
commonSubTypeGeneral(t, t2)
)
}
-
- cached
- predicate outRefReturnNode(Ssa::ExplicitDefinition def, OutRefReturnKind kind) {
- exists(Parameter p |
- def.isLiveOutRefParameterDefinition(p) and
- kind.getPosition() = p.getPosition()
- |
- p.isOut() and kind instanceof OutReturnKind
- or
- p.isRef() and kind instanceof RefReturnKind
- )
- }
-
- cached
- predicate summaryOutNodeCached(DataFlowCall c, Node out, ReturnKind rk) {
- FlowSummaryImpl::Private::summaryOutNode(c, out, rk)
- }
-
- cached
- predicate summaryArgumentNodeCached(DataFlowCall c, Node arg, int i) {
- FlowSummaryImpl::Private::summaryArgumentNode(c, arg, i)
- }
-
- cached
- predicate summaryPostUpdateNodeCached(Node post, ParameterNode pre) {
- FlowSummaryImpl::Private::summaryPostUpdateNode(post, pre)
- }
-
- cached
- predicate summaryReturnNodeCached(Node ret, ReturnKind rk) {
- FlowSummaryImpl::Private::summaryReturnNode(ret, rk) and
- not rk instanceof JumpReturnKind
- }
-
- cached
- predicate castNode(Node n) {
- n.asExpr() instanceof Cast
- or
- n.(AssignableDefinitionNode).getDefinition() instanceof AssignableDefinitions::PatternDefinition
- }
-
- /** Holds if `n` should be hidden from path explanations. */
- cached
- predicate nodeIsHidden(Node n) {
- exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
- def instanceof Ssa::PhiNode
- or
- def instanceof Ssa::ImplicitEntryDefinition
- or
- def instanceof Ssa::ImplicitCallDefinition
- )
- or
- exists(Parameter p |
- p = n.(ParameterNode).getParameter() and
- not p.fromSource()
- )
- or
- n = TInstanceParameterNode(any(Callable c | not c.fromSource()))
- or
- n instanceof YieldReturnNode
- or
- n instanceof AsyncReturnNode
- or
- n instanceof ImplicitCapturedArgumentNode
- or
- n instanceof MallocNode
- or
- n instanceof SummaryNode
- or
- n instanceof ParamsArgumentNode
- or
- n.asExpr() = any(WithExpr we).getInitializer()
- }
-
- cached
- predicate parameterNode(Node n, DataFlowCallable c, int i) {
- n.(ParameterNodeImpl).isParameterOf(c, i)
- }
-
- cached
- predicate argumentNode(Node n, DataFlowCall call, int pos) {
- n.(ArgumentNodeImpl).argumentOf(call, pos)
- }
}
import Cached
+/** Holds if `n` should be hidden from path explanations. */
+predicate nodeIsHidden(Node n) {
+ exists(Ssa::Definition def | def = n.(SsaDefinitionNode).getDefinition() |
+ def instanceof Ssa::PhiNode
+ or
+ def instanceof Ssa::ImplicitEntryDefinition
+ or
+ def instanceof Ssa::ImplicitCallDefinition
+ )
+ or
+ exists(Parameter p |
+ p = n.(ParameterNode).getParameter() and
+ not p.fromSource()
+ )
+ or
+ n = TInstanceParameterNode(any(Callable c | not c.fromSource()))
+ or
+ n instanceof YieldReturnNode
+ or
+ n instanceof AsyncReturnNode
+ or
+ n instanceof ImplicitCapturedArgumentNode
+ or
+ n instanceof MallocNode
+ or
+ n instanceof SummaryNode
+ or
+ n instanceof ParamsArgumentNode
+ or
+ n.asExpr() = any(WithExpr we).getInitializer()
+}
+
/** An SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode {
Ssa::Definition def;
@@ -1142,10 +941,12 @@ import ParameterNodes
/** A data-flow node that represents a call argument. */
class ArgumentNode extends Node {
- ArgumentNode() { argumentNode(this, _, _) }
+ ArgumentNode() { this instanceof ArgumentNodeImpl }
/** Holds if this argument occurs at the given position in the given call. */
- final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
+ final predicate argumentOf(DataFlowCall call, int pos) {
+ this.(ArgumentNodeImpl).argumentOf(call, pos)
+ }
}
abstract private class ArgumentNodeImpl extends Node {
@@ -1310,14 +1111,10 @@ private module ArgumentNodes {
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
- private DataFlowCall c;
- private int i;
-
- SummaryArgumentNode() { summaryArgumentNodeCached(c, this, i) }
+ SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
override predicate argumentOf(DataFlowCall call, int pos) {
- call = c and
- i = pos
+ FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
}
}
}
@@ -1352,7 +1149,16 @@ private module ReturnNodes {
class OutRefReturnNode extends ReturnNode, SsaDefinitionNode {
OutRefReturnKind kind;
- OutRefReturnNode() { outRefReturnNode(this.getDefinition(), kind) }
+ OutRefReturnNode() {
+ exists(Parameter p |
+ this.getDefinition().isLiveOutRefParameterDefinition(p) and
+ kind.getPosition() = p.getPosition()
+ |
+ p.isOut() and kind instanceof OutReturnKind
+ or
+ p.isRef() and kind instanceof RefReturnKind
+ )
+ }
override ReturnKind getKind() { result = kind }
}
@@ -1449,7 +1255,10 @@ private module ReturnNodes {
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private ReturnKind rk;
- SummaryReturnNode() { summaryReturnNodeCached(this, rk) }
+ SummaryReturnNode() {
+ FlowSummaryImpl::Private::summaryReturnNode(this, rk) and
+ not rk instanceof JumpReturnKind
+ }
override ReturnKind getKind() { result = rk }
}
@@ -1460,7 +1269,6 @@ import ReturnNodes
/** A data-flow node that represents the output of a call. */
abstract class OutNode extends Node {
/** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
- cached
abstract DataFlowCall getCall(ReturnKind kind);
}
@@ -1488,7 +1296,6 @@ private module OutNodes {
}
override DataFlowCall getCall(ReturnKind kind) {
- Stages::DataFlowStage::forceCachingInSameStage() and
result = call and
(
kind instanceof NormalReturnKind and
@@ -1564,14 +1371,10 @@ private module OutNodes {
}
private class SummaryOutNode extends SummaryNode, OutNode {
- private DataFlowCall c;
- private ReturnKind rk;
-
- SummaryOutNode() { summaryOutNodeCached(c, this, rk) }
+ SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
override DataFlowCall getCall(ReturnKind kind) {
- result = c and
- kind = rk
+ FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
}
}
}
@@ -1654,7 +1457,29 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
}
}
-predicate jumpStep = jumpStepImpl/2;
+/**
+ * Holds if `pred` can flow to `succ`, by jumping from one callable to
+ * another. Additional steps specified by the configuration are *not*
+ * taken into account.
+ */
+predicate jumpStep(Node pred, Node succ) {
+ pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
+ or
+ exists(FieldOrProperty fl, FieldOrPropertyRead flr |
+ fl.isStatic() and
+ fl.isFieldLike() and
+ fl.getAnAssignedValue() = pred.asExpr() and
+ fl.getAnAccess() = flr and
+ flr = succ.asExpr() and
+ flr.hasNonlocalValue()
+ )
+ or
+ exists(JumpReturnKind jrk, DataFlowCall call |
+ FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
+ viableCallable(call) = jrk.getTarget() and
+ succ = getAnOutNode(call, jrk.getTargetReturnKind())
+ )
+}
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
StoreStepConfiguration() { this = "StoreStepConfiguration" }
@@ -1675,7 +1500,46 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
}
}
-predicate storeStep = storeStepImpl/3;
+pragma[nomagic]
+private PropertyContent getResultContent() {
+ result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty()
+}
+
+/**
+ * Holds if data can flow from `node1` to `node2` via an assignment to
+ * content `c`.
+ */
+predicate storeStep(Node node1, Content c, Node node2) {
+ exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
+ hasNodePath(x, node1, node) and
+ if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
+ |
+ fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
+ or
+ arrayStore(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
+ )
+ or
+ exists(StoreStepConfiguration x, Expr arg, ControlFlow::Node callCfn |
+ x.hasExprPath(arg, node1.(ExprNode).getControlFlowNode(), _, callCfn) and
+ node2 = TParamsArgumentNode(callCfn) and
+ isParamsArg(_, arg, _) and
+ c instanceof ElementContent
+ )
+ or
+ exists(Expr e |
+ e = node1.asExpr() and
+ node2.(YieldReturnNode).getYieldReturnStmt().getExpr() = e and
+ c instanceof ElementContent
+ )
+ or
+ exists(Expr e |
+ e = node1.asExpr() and
+ node2.(AsyncReturnNode).getExpr() = e and
+ c = getResultContent()
+ )
+ or
+ FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
+}
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
ReadStepConfiguration() { this = "ReadStepConfiguration" }
@@ -1742,7 +1606,99 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
}
}
-predicate readStep = readStepImpl/3;
+/**
+ * Holds if data can flow from `node1` to `node2` via a read of content `c`.
+ */
+predicate readStep(Node node1, Content c, Node node2) {
+ exists(ReadStepConfiguration x |
+ hasNodePath(x, node1, node2) and
+ fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
+ or
+ hasNodePath(x, node1, node2) and
+ arrayRead(node1.asExpr(), node2.asExpr()) and
+ c instanceof ElementContent
+ or
+ exists(ForeachStmt fs, Ssa::ExplicitDefinition def |
+ x.hasDefPath(fs.getIterableExpr(), node1.getControlFlowNode(), def.getADefinition(),
+ def.getControlFlowNode()) and
+ node2.(SsaDefinitionNode).getDefinition() = def and
+ c instanceof ElementContent
+ )
+ or
+ hasNodePath(x, node1, node2) and
+ node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
+ c = getResultContent()
+ or
+ // node1 = (..., node2, ...)
+ // node1.ItemX flows to node2
+ exists(TupleExpr te, int i, Expr item |
+ te = node1.asExpr() and
+ not te.isConstruction() and
+ c.(FieldContent).getField() = te.getType().(TupleType).getElement(i).getUnboundDeclaration() and
+ // node1 = (..., item, ...)
+ te.getArgument(i) = item
+ |
+ // item = (..., ..., ...) in node1 = (..., (..., ..., ...), ...)
+ node2.asExpr().(TupleExpr) = item and
+ hasNodePath(x, node1, node2)
+ or
+ // item = variable in node1 = (..., variable, ...)
+ exists(AssignableDefinitions::TupleAssignmentDefinition tad, Ssa::ExplicitDefinition def |
+ node2.(SsaDefinitionNode).getDefinition() = def and
+ def.getADefinition() = tad and
+ tad.getLeaf() = item and
+ hasNodePath(x, node1, node2)
+ )
+ or
+ // item = variable in node1 = (..., variable, ...) in a case/is var (..., ...)
+ te = any(PatternExpr pe).getAChildExpr*() and
+ exists(AssignableDefinitions::LocalVariableDefinition lvd, Ssa::ExplicitDefinition def |
+ node2.(SsaDefinitionNode).getDefinition() = def and
+ def.getADefinition() = lvd and
+ lvd.getDeclaration() = item and
+ hasNodePath(x, node1, node2)
+ )
+ )
+ )
+ or
+ FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
+}
+
+/**
+ * Holds if values stored inside content `c` are cleared at node `n`. For example,
+ * any value stored inside `f` is cleared at the pre-update node associated with `x`
+ * in `x.f = newValue`.
+ */
+predicate clearsContent(Node n, Content c) {
+ fieldOrPropertyStore(_, c, _, n.asExpr(), true)
+ or
+ fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
+ or
+ FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) and
+ not c instanceof ElementContent
+ or
+ FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
+ or
+ exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
+ oi = we.getInitializer() and
+ n.asExpr() = oi and
+ f = oi.getAMemberInitializer().getInitializedMember() and
+ c = f.getContent()
+ )
+}
+
+/**
+ * Holds if the node `n` is unreachable when the call context is `call`.
+ */
+predicate isUnreachableInCall(Node n, DataFlowCall call) {
+ exists(
+ ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
+ |
+ viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
+ paramNode.getSsaDefinition().getARead() = guard and
+ guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
+ )
+}
/**
* An entity used to represent the type of data-flow node. Two nodes will have
@@ -1753,10 +1709,7 @@ predicate readStep = readStepImpl/3;
* `DataFlowType`, while `Func` and `Func` are not, because
* `string` is not a type parameter.
*/
-class DataFlowType extends Gvn::GvnType {
- pragma[nomagic]
- DataFlowType() { this = any(NodeImpl n).getDataFlowType() }
-}
+class DataFlowType = Gvn::GvnType;
/** Gets the type of `n` used for type pruning. */
pragma[inline]
@@ -1888,11 +1841,11 @@ private module PostUpdateNodes {
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
- private Node pre;
+ SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) }
- SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
-
- override Node getPreUpdateNode() { result = pre }
+ override Node getPreUpdateNode() {
+ FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
+ }
}
}
@@ -1900,7 +1853,12 @@ private import PostUpdateNodes
/** A node that performs a type cast. */
class CastNode extends Node {
- CastNode() { castNode(this) }
+ CastNode() {
+ this.asExpr() instanceof Cast
+ or
+ this.(AssignableDefinitionNode).getDefinition() instanceof
+ AssignableDefinitions::PatternDefinition
+ }
}
class DataFlowExpr = DotNet::Expr;
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll
index 12a62faf387..bfc2f5469d0 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll
@@ -67,6 +67,8 @@ class Node extends TNode {
}
}
+private class TExprNode_ = TExprNode or TCilExprNode;
+
/**
* An expression, viewed as a node in a data flow graph.
*
@@ -74,9 +76,7 @@ class Node extends TNode {
* to multiple `ExprNode`s, just like it may correspond to multiple
* `ControlFlow::Node`s.
*/
-class ExprNode extends Node {
- ExprNode() { this = TExprNode(_) or this = TCilExprNode(_) }
-
+class ExprNode extends Node, TExprNode_ {
/** Gets the expression corresponding to this node. */
DotNet::Expr getExpr() {
result = this.getExprAtNode(_)
@@ -99,7 +99,7 @@ class ExprNode extends Node {
* flow graph.
*/
class ParameterNode extends Node {
- ParameterNode() { parameterNode(this, _, _) }
+ ParameterNode() { this instanceof ParameterNodeImpl }
/** Gets the parameter corresponding to this node, if any. */
DotNet::Parameter getParameter() {
@@ -110,7 +110,9 @@ class ParameterNode extends Node {
* Holds if this node is the parameter of callable `c` at the specified
* (zero-based) position.
*/
- predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
+ predicate isParameterOf(DataFlowCallable c, int i) {
+ this.(ParameterNodeImpl).isParameterOf(c, i)
+ }
}
/** A definition, viewed as a node in a data flow graph. */
diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
index 72525d3234a..462838abcd1 100755
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
@@ -1,6 +1,5 @@
private import csharp
private import TaintTrackingPublic
-private import DataFlowImplCommon
private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.Caching
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
@@ -79,7 +78,6 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
}
private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
- Stages::DataFlowStage::forceCachingInSameStage() and
hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo)
or
localTaintStepCil(nodeFrom, nodeTo)
@@ -87,6 +85,11 @@ private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node n
cached
private module Cached {
+ private import DataFlowImplCommon as DataFlowImplCommon
+
+ cached
+ predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
+
/**
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
From bd0a196a397cd30d92f45b8d7e5db5dbfa2733c3 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 26 Apr 2021 20:19:43 +0200
Subject: [PATCH 115/550] Java: Update data-flow caching
---
.../java/dataflow/internal/DataFlowNodes.qll | 109 +++++++-----------
.../dataflow/internal/DataFlowPrivate.qll | 1 -
.../java/dataflow/internal/DataFlowUtil.qll | 2 +
.../dataflow/internal/TaintTrackingUtil.qll | 108 +++++++++--------
4 files changed, 107 insertions(+), 113 deletions(-)
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowNodes.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowNodes.qll
index 552849c2c34..c47efa287ad 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowNodes.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowNodes.qll
@@ -4,71 +4,48 @@ private import semmle.code.java.dataflow.FlowSummary
private import semmle.code.java.dataflow.TypeFlow
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
+private import DataFlowImplCommon as DataFlowImplCommon
cached
-private module Cached {
- cached
- newtype TNode =
- TExprNode(Expr e) {
- not e.getType() instanceof VoidType and
- not e.getParent*() instanceof Annotation
- } or
- TExplicitParameterNode(Parameter p) {
- exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
- } or
- TImplicitVarargsArray(Call c) {
- c.getCallee().isVarargs() and
- not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
- } or
- TInstanceParameterNode(Callable c) {
- (exists(c.getBody()) or c instanceof SummarizedCallable) and
- not c.isStatic()
- } or
- TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
- TMallocNode(ClassInstanceExpr cie) or
- TExplicitExprPostUpdate(Expr e) {
- explicitInstanceArgument(_, e)
- or
- e instanceof Argument and not e.getType() instanceof ImmutableType
- or
- exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
- or
- exists(ArrayAccess aa | e = aa.getArray())
- } or
- TImplicitExprPostUpdate(InstanceAccessExt ia) {
- implicitInstanceArgument(_, ia)
- or
- exists(FieldAccess fa |
- fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
- )
- } or
- TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
- FlowSummaryImpl::Private::summaryNodeRange(c, state)
- }
-
- cached
- predicate summaryOutNodeCached(DataFlowCall c, Node out) {
- FlowSummaryImpl::Private::summaryOutNode(c, out, _)
+newtype TNode =
+ TExprNode(Expr e) {
+ DataFlowImplCommon::forceCachingInSameStage() and
+ not e.getType() instanceof VoidType and
+ not e.getParent*() instanceof Annotation
+ } or
+ TExplicitParameterNode(Parameter p) {
+ exists(p.getCallable().getBody()) or p.getCallable() instanceof SummarizedCallable
+ } or
+ TImplicitVarargsArray(Call c) {
+ c.getCallee().isVarargs() and
+ not exists(Argument arg | arg.getCall() = c and arg.isExplicitVarargsArray())
+ } or
+ TInstanceParameterNode(Callable c) {
+ (exists(c.getBody()) or c instanceof SummarizedCallable) and
+ not c.isStatic()
+ } or
+ TImplicitInstanceAccess(InstanceAccessExt ia) { not ia.isExplicit(_) } or
+ TMallocNode(ClassInstanceExpr cie) or
+ TExplicitExprPostUpdate(Expr e) {
+ explicitInstanceArgument(_, e)
+ or
+ e instanceof Argument and not e.getType() instanceof ImmutableType
+ or
+ exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier())
+ or
+ exists(ArrayAccess aa | e = aa.getArray())
+ } or
+ TImplicitExprPostUpdate(InstanceAccessExt ia) {
+ implicitInstanceArgument(_, ia)
+ or
+ exists(FieldAccess fa |
+ fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
+ )
+ } or
+ TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
+ FlowSummaryImpl::Private::summaryNodeRange(c, state)
}
- cached
- predicate summaryArgumentNodeCached(DataFlowCall c, Node arg, int i) {
- FlowSummaryImpl::Private::summaryArgumentNode(c, arg, i)
- }
-
- cached
- predicate summaryPostUpdateNodeCached(Node post, ParameterNode pre) {
- FlowSummaryImpl::Private::summaryPostUpdateNode(post, pre)
- }
-
- cached
- predicate summaryReturnNodeCached(Node ret) {
- FlowSummaryImpl::Private::summaryReturnNode(ret, _)
- }
-}
-
-private import Cached
-
private predicate explicitInstanceArgument(Call call, Expr instarg) {
call instanceof MethodAccess and
instarg = call.getQualifier() and
@@ -404,13 +381,15 @@ module Private {
override string toString() { result = "[summary] " + state + " in " + c }
/** Holds if this summary node is the `i`th argument of `call`. */
- predicate isArgumentOf(DataFlowCall call, int i) { summaryArgumentNodeCached(call, this, i) }
+ predicate isArgumentOf(DataFlowCall call, int i) {
+ FlowSummaryImpl::Private::summaryArgumentNode(call, this, i)
+ }
/** Holds if this summary node is a return node. */
- predicate isReturn() { summaryReturnNodeCached(this) }
+ predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this, _) }
/** Holds if this summary node is an out node for `call`. */
- predicate isOut(DataFlowCall call) { summaryOutNodeCached(call, this) }
+ predicate isOut(DataFlowCall call) { FlowSummaryImpl::Private::summaryOutNode(call, this, _) }
}
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
@@ -439,7 +418,7 @@ private class MallocNode extends Node, TMallocNode {
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
- SummaryPostUpdateNode() { summaryPostUpdateNodeCached(this, pre) }
+ SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
override Node getPreUpdateNode() { result = pre }
}
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll
index 23d84c10c9f..5756c56ba6d 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll
@@ -284,7 +284,6 @@ private class ConstantBooleanArgumentNode extends ArgumentNode, ExprNode {
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/
-cached
predicate isUnreachableInCall(Node n, DataFlowCall call) {
exists(
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param,
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll
index 2ad09574015..e25ab24cfbb 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll
@@ -11,6 +11,7 @@ private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.FlowSummary
import semmle.code.java.dataflow.InstanceAccess
private import FlowSummaryImpl as FlowSummaryImpl
+private import TaintTrackingUtil as TaintTrackingUtil
import DataFlowNodes::Public
/** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */
@@ -112,6 +113,7 @@ predicate localFlowStep(Node node1, Node node2) {
*/
cached
predicate simpleLocalFlowStep(Node node1, Node node2) {
+ TaintTrackingUtil::forceCachingInSameStage() and
// Variable flow steps through adjacent def-use and use-use pairs.
exists(SsaExplicitUpdate upd |
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
diff --git a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll
index f9278ab815e..8c514e357d2 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll
@@ -29,55 +29,69 @@ predicate localExprTaint(Expr src, Expr sink) {
localTaint(DataFlow::exprNode(src), DataFlow::exprNode(sink))
}
-/**
- * Holds if taint can flow in one local step from `src` to `sink`.
- */
-predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
- DataFlow::localFlowStep(src, sink) or
- localAdditionalTaintStep(src, sink) or
- // Simple flow through library code is included in the exposed local
- // step relation, even though flow is technically inter-procedural
- FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
+cached
+private module Cached {
+ private import DataFlowImplCommon as DataFlowImplCommon
+
+ cached
+ predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
+
+ /**
+ * Holds if taint can flow in one local step from `src` to `sink`.
+ */
+ cached
+ predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
+ DataFlow::localFlowStep(src, sink) or
+ localAdditionalTaintStep(src, sink) or
+ // Simple flow through library code is included in the exposed local
+ // step relation, even though flow is technically inter-procedural
+ FlowSummaryImpl::Private::Steps::summaryThroughStep(src, sink, false)
+ }
+
+ /**
+ * Holds if taint can flow in one local step from `src` to `sink` excluding
+ * local data flow steps. That is, `src` and `sink` are likely to represent
+ * different objects.
+ */
+ cached
+ predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
+ localAdditionalTaintExprStep(src.asExpr(), sink.asExpr())
+ or
+ localAdditionalTaintUpdateStep(src.asExpr(),
+ sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
+ or
+ exists(Argument arg |
+ src.asExpr() = arg and
+ arg.isVararg() and
+ sink.(DataFlow::ImplicitVarargsArray).getCall() = arg.getCall()
+ )
+ or
+ FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
+ }
+
+ /**
+ * Holds if the additional step from `src` to `sink` should be included in all
+ * global taint flow configurations.
+ */
+ cached
+ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
+ localAdditionalTaintStep(src, sink) or
+ any(AdditionalTaintStep a).step(src, sink)
+ }
+
+ /**
+ * Holds if `node` should be a sanitizer in all global taint flow configurations
+ * but not in local taint.
+ */
+ cached
+ predicate defaultTaintSanitizer(DataFlow::Node node) {
+ // Ignore paths through test code.
+ node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
+ node.asExpr() instanceof ValidatedVariableAccess
+ }
}
-/**
- * Holds if taint can flow in one local step from `src` to `sink` excluding
- * local data flow steps. That is, `src` and `sink` are likely to represent
- * different objects.
- */
-predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
- localAdditionalTaintExprStep(src.asExpr(), sink.asExpr())
- or
- localAdditionalTaintUpdateStep(src.asExpr(),
- sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
- or
- exists(Argument arg |
- src.asExpr() = arg and
- arg.isVararg() and
- sink.(DataFlow::ImplicitVarargsArray).getCall() = arg.getCall()
- )
- or
- FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
-}
-
-/**
- * Holds if the additional step from `src` to `sink` should be included in all
- * global taint flow configurations.
- */
-predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
- localAdditionalTaintStep(src, sink) or
- any(AdditionalTaintStep a).step(src, sink)
-}
-
-/**
- * Holds if `node` should be a sanitizer in all global taint flow configurations
- * but not in local taint.
- */
-predicate defaultTaintSanitizer(DataFlow::Node node) {
- // Ignore paths through test code.
- node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
- node.asExpr() instanceof ValidatedVariableAccess
-}
+import Cached
/**
* Holds if taint can flow in one local step from `src` to `sink` excluding
From 5eb96c1e4533729483037138d2719b729d79e521 Mon Sep 17 00:00:00 2001
From: edvraa <80588099+edvraa@users.noreply.github.com>
Date: Tue, 27 Apr 2021 20:26:29 +0300
Subject: [PATCH 116/550] Remove Class cast
---
java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql
index ad75e993c30..3b8b5dc759a 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql
@@ -39,7 +39,7 @@ class RegexSink extends DataFlow::ExprNode {
m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "RegExUtils") and
(
ma.getArgument(1) = this.asExpr() and
- m.getParameterType(1).(Class) instanceof TypeString and
+ m.getParameterType(1) instanceof TypeString and
m.hasName([
"removeAll", "removeFirst", "removePattern", "replaceAll", "replaceFirst",
"replacePattern"
From 7adc3c2fba0ef298fba66f767404ca55ad5ccda7 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 17:25:10 +0100
Subject: [PATCH 117/550] Upload ReDoS query, qhelp and tests
---
python/ql/src/Security/CWE-400/RegexDoS.qhelp | 27 ++++++
python/ql/src/Security/CWE-400/RegexDoS.ql | 82 +++++++++++++++++++
.../ql/src/Security/CWE-400/tests/re_bad.py | 22 +++++
.../ql/src/Security/CWE-400/tests/re_good.py | 22 +++++
4 files changed, 153 insertions(+)
create mode 100644 python/ql/src/Security/CWE-400/RegexDoS.qhelp
create mode 100644 python/ql/src/Security/CWE-400/RegexDoS.ql
create mode 100644 python/ql/src/Security/CWE-400/tests/re_bad.py
create mode 100644 python/ql/src/Security/CWE-400/tests/re_good.py
diff --git a/python/ql/src/Security/CWE-400/RegexDoS.qhelp b/python/ql/src/Security/CWE-400/RegexDoS.qhelp
new file mode 100644
index 00000000000..de564c83347
--- /dev/null
+++ b/python/ql/src/Security/CWE-400/RegexDoS.qhelp
@@ -0,0 +1,27 @@
+
+
+
+
+ If aregular expression is built by a not escaped user-provided value, a user is likely to be able to cause a Denial of Service.
+
+
+
+ In case user input must compose a regular expression, it should be escaped with functions such as re.escape.
+
+
+
+
+ OWASP
+ Regular Expression DoS
+
+
+ SonarSource
+ RSPEC-2631
+
+
+ CWE-
+ 400
+
+
+
+
\ No newline at end of file
diff --git a/python/ql/src/Security/CWE-400/RegexDoS.ql b/python/ql/src/Security/CWE-400/RegexDoS.ql
new file mode 100644
index 00000000000..fbdca996e55
--- /dev/null
+++ b/python/ql/src/Security/CWE-400/RegexDoS.ql
@@ -0,0 +1,82 @@
+/**
+ * @name Python Regex DoS
+ * @description Python Regular Expression Denial of Service
+ * @kind path-problem
+ * @problem.severity error
+ * @id python/regex-dos
+ * @tags experimental
+ * security
+ * external/cwe/cwe-400
+ */
+
+import python
+import semmle.python.dataflow.new.RemoteFlowSources
+import semmle.python.dataflow.new.DataFlow
+import semmle.python.dataflow.new.TaintTracking
+import semmle.python.dataflow.new.internal.TaintTrackingPublic
+import DataFlow::PathGraph
+
+class ReMethods extends string {
+ ReMethods() {
+ this = "match" or
+ this = "fullmatch" or
+ this = "search" or
+ this = "split" or
+ this = "findall" or
+ this = "finditer"
+ }
+}
+
+class DirectRegex extends DataFlow::Node {
+ DirectRegex() {
+ exists(string reMethod, CallNode reCall |
+ reMethod instanceof ReMethods and
+ reCall = Value::named("re." + reMethod).getACall() and
+ this.asExpr() = reCall.getArg(0).getNode()
+ )
+ }
+}
+
+class CompiledRegex extends DataFlow::Node {
+ CompiledRegex() {
+ exists(CallNode patternCall, SsaVariable patternVar, CallNode reMethodCall |
+ patternCall = Value::named("re.compile").getACall() and
+ patternVar.getDefinition().getImmediateDominator() = patternCall and
+ patternVar.getAUse().getNode() = reMethodCall.getNode().getFunc().(Attribute).getObject() and
+ reMethodCall.getNode().getFunc().(Attribute).getName() instanceof ReMethods and
+ this.asExpr() = patternCall.getArg(0).getNode()
+ )
+ }
+}
+
+class RegexDoSSink extends DataFlow::Node {
+ RegexDoSSink() { this instanceof DirectRegex or this instanceof CompiledRegex }
+}
+
+class EscapeSanitizer extends DataFlow::Node {
+ EscapeSanitizer() {
+ exists(Call c |
+ (
+ // avoid flow through any %escape% function
+ c.getFunc().(Attribute).getName().matches("%escape%") or // something.%escape%()
+ c.getFunc().(Name).getId().matches("%escape%") // %escape%()
+ ) and
+ this.asExpr() = c
+ )
+ }
+}
+
+class RegexDoSFlowConfig extends TaintTracking::Configuration {
+ RegexDoSFlowConfig() { this = "RegexDoSFlowConfig" }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof RegexDoSSink }
+
+ override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof EscapeSanitizer }
+}
+
+from RegexDoSFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
+where config.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "$@ regex operation includes $@.", sink.getNode(), "This",
+ source.getNode(), "a user-provided value"
diff --git a/python/ql/src/Security/CWE-400/tests/re_bad.py b/python/ql/src/Security/CWE-400/tests/re_bad.py
new file mode 100644
index 00000000000..6a0aa7c6614
--- /dev/null
+++ b/python/ql/src/Security/CWE-400/tests/re_bad.py
@@ -0,0 +1,22 @@
+from flask import request, Flask
+import re
+
+app = Flask(__name__)
+
+
+@app.route("/direct")
+def direct():
+ pattern = request.args['pattern']
+
+ re.search(pattern, "")
+
+
+@app.route("/compile")
+def compile():
+ pattern = re.compile(request.args['pattern'])
+
+ pattern.search("")
+
+
+# if __name__ == "__main__":
+# app.run(debug=True)
diff --git a/python/ql/src/Security/CWE-400/tests/re_good.py b/python/ql/src/Security/CWE-400/tests/re_good.py
new file mode 100644
index 00000000000..ba09b1fe30b
--- /dev/null
+++ b/python/ql/src/Security/CWE-400/tests/re_good.py
@@ -0,0 +1,22 @@
+from flask import request, Flask
+import re
+
+app = Flask(__name__)
+
+
+@app.route("/direct")
+def direct():
+ pattern = re.escape(request.args['pattern'])
+
+ re.search(pattern, "")
+
+
+@app.route("/compile")
+def compile():
+ pattern = re.compile(re.escape(request.args['pattern']))
+
+ pattern.search("")
+
+
+# if __name__ == "__main__":
+# app.run(debug=True)
From bd3d2ec686ad9686180f8d6ec94d74c4703f2c1f Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 19:44:23 +0100
Subject: [PATCH 118/550] Update to match consistent naming across languages
---
.../{CWE-400 => CWE-730}/RegexDoS.qhelp | 4 +++
.../Security/{CWE-400 => CWE-730}/RegexDoS.ql | 30 +++++++++++--------
.../{CWE-400 => CWE-730}/tests/re_bad.py | 0
.../{CWE-400 => CWE-730}/tests/re_good.py | 0
4 files changed, 21 insertions(+), 13 deletions(-)
rename python/ql/src/Security/{CWE-400 => CWE-730}/RegexDoS.qhelp (88%)
rename python/ql/src/Security/{CWE-400 => CWE-730}/RegexDoS.ql (66%)
rename python/ql/src/Security/{CWE-400 => CWE-730}/tests/re_bad.py (100%)
rename python/ql/src/Security/{CWE-400 => CWE-730}/tests/re_good.py (100%)
diff --git a/python/ql/src/Security/CWE-400/RegexDoS.qhelp b/python/ql/src/Security/CWE-730/RegexDoS.qhelp
similarity index 88%
rename from python/ql/src/Security/CWE-400/RegexDoS.qhelp
rename to python/ql/src/Security/CWE-730/RegexDoS.qhelp
index de564c83347..22f328e852b 100644
--- a/python/ql/src/Security/CWE-400/RegexDoS.qhelp
+++ b/python/ql/src/Security/CWE-730/RegexDoS.qhelp
@@ -22,6 +22,10 @@
CWE-
400
+
+ CWE-
+ 730
+