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.
\ No newline at end of file
From 21f8135fa6824f42bdf643d48c34b1a712cbe715 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 20:19:08 +0100
Subject: [PATCH 024/168] Move to experimental folder
---
python/ql/src/{ => experimental}/Security/CWE-730/RegexDoS.qhelp | 0
python/ql/src/{ => experimental}/Security/CWE-730/RegexDoS.ql | 0
python/ql/src/{ => experimental}/Security/CWE-730/tests/re_bad.py | 0
.../ql/src/{ => experimental}/Security/CWE-730/tests/re_good.py | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename python/ql/src/{ => experimental}/Security/CWE-730/RegexDoS.qhelp (100%)
rename python/ql/src/{ => experimental}/Security/CWE-730/RegexDoS.ql (100%)
rename python/ql/src/{ => experimental}/Security/CWE-730/tests/re_bad.py (100%)
rename python/ql/src/{ => experimental}/Security/CWE-730/tests/re_good.py (100%)
diff --git a/python/ql/src/Security/CWE-730/RegexDoS.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexDoS.qhelp
similarity index 100%
rename from python/ql/src/Security/CWE-730/RegexDoS.qhelp
rename to python/ql/src/experimental/Security/CWE-730/RegexDoS.qhelp
diff --git a/python/ql/src/Security/CWE-730/RegexDoS.ql b/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
similarity index 100%
rename from python/ql/src/Security/CWE-730/RegexDoS.ql
rename to python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
diff --git a/python/ql/src/Security/CWE-730/tests/re_bad.py b/python/ql/src/experimental/Security/CWE-730/tests/re_bad.py
similarity index 100%
rename from python/ql/src/Security/CWE-730/tests/re_bad.py
rename to python/ql/src/experimental/Security/CWE-730/tests/re_bad.py
diff --git a/python/ql/src/Security/CWE-730/tests/re_good.py b/python/ql/src/experimental/Security/CWE-730/tests/re_good.py
similarity index 100%
rename from python/ql/src/Security/CWE-730/tests/re_good.py
rename to python/ql/src/experimental/Security/CWE-730/tests/re_good.py
From 6cc714464c519dd59bbc4456f312ca6b1b10a984 Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Thu, 18 Mar 2021 22:42:49 +0100
Subject: [PATCH 025/168] Apply suggestions from code review
Co-authored-by: yoff
---
.../experimental/Security/CWE-730/RegexDoS.ql | 27 +++++++------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql b/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
index 79905fe6921..b89835aad8a 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
@@ -21,34 +21,25 @@ import DataFlow::PathGraph
// Should this be moved to a different structure? (For other queries to be able to use it)
class ReMethods extends string {
- ReMethods() {
- this = "match" or
- this = "fullmatch" or
- this = "search" or
- this = "split" or
- this = "findall" or
- this = "finditer"
- }
+ ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "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()
+ exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
+ reCall = API::moduleImport("re").getMember(reMethod).getACall() and
+ this = reCall.getArg(0)
)
}
}
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()
+ exists(DataFlow::CallCfgNode patternCall, AttrRead reMethod |
+ patternCall = API::moduleImport("re").getMember("compile").getACall() and
+ patternCall = reMethod.getObject().getALocalSource() and
+ reMethod.getAttributeName() instanceof ReMethods and
+ this = patternCall.getArg(0)
)
}
}
From 63f708dd57e53bd3f4cb0c73aa865384933a1789 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 23:03:33 +0100
Subject: [PATCH 026/168] Apply suggestions
---
python/ql/src/experimental/Security/CWE-730/RegexDoS.ql | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql b/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
index b89835aad8a..d35b596c045 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
@@ -17,11 +17,12 @@ 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 semmle.python.ApiGraphs
import DataFlow::PathGraph
// Should this be moved to a different structure? (For other queries to be able to use it)
class ReMethods extends string {
- ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }```
+ ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
}
class DirectRegex extends DataFlow::Node {
@@ -35,7 +36,7 @@ class DirectRegex extends DataFlow::Node {
class CompiledRegex extends DataFlow::Node {
CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, AttrRead reMethod |
+ exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
reMethod.getAttributeName() instanceof ReMethods and
From 5dae9207831dbe30365235ef03e9c28357172668 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 23:04:47 +0100
Subject: [PATCH 027/168] Edit filenames to match consistent naming
---
.../Security/CWE-730/{RegexDoS.qhelp => RegexInjection.qhelp} | 0
.../Security/CWE-730/{RegexDoS.ql => RegexInjection.ql} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename python/ql/src/experimental/Security/CWE-730/{RegexDoS.qhelp => RegexInjection.qhelp} (100%)
rename python/ql/src/experimental/Security/CWE-730/{RegexDoS.ql => RegexInjection.ql} (100%)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexDoS.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/RegexDoS.qhelp
rename to python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexDoS.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/RegexDoS.ql
rename to python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
From f45307f9906e581a527710eb5b6a1bf224a36c56 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 23:33:10 +0100
Subject: [PATCH 028/168] Apply rebase
---
.../Security/CWE-730/RegexInjection.qhelp | 0
.../ql/src/Security/CWE-730/RegexInjection.ql | 22 ++++++
.../tests => Security/CWE-730}/re_bad.py | 0
.../tests => Security/CWE-730}/re_good.py | 0
.../Security/CWE-730/RegexInjection.ql | 78 -------------------
python/ql/src/semmle/python/Concepts.qll | 43 ++++++++++
.../security/dataflow/RegexInjection.qll | 23 ++++++
7 files changed, 88 insertions(+), 78 deletions(-)
rename python/ql/src/{experimental => }/Security/CWE-730/RegexInjection.qhelp (100%)
create mode 100644 python/ql/src/Security/CWE-730/RegexInjection.ql
rename python/ql/src/{experimental/Security/CWE-730/tests => Security/CWE-730}/re_bad.py (100%)
rename python/ql/src/{experimental/Security/CWE-730/tests => Security/CWE-730}/re_good.py (100%)
delete mode 100644 python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
create mode 100644 python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/Security/CWE-730/RegexInjection.qhelp
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
rename to python/ql/src/Security/CWE-730/RegexInjection.qhelp
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql
new file mode 100644
index 00000000000..27bbe69529d
--- /dev/null
+++ b/python/ql/src/Security/CWE-730/RegexInjection.ql
@@ -0,0 +1,22 @@
+/**
+ * @name Regular expression injection
+ * @description User input should not be used in regular expressions without first being escaped,
+ * otherwise a malicious user may be able to inject an expression that could require
+ * exponential time on certain inputs.
+ * @kind path-problem
+ * @problem.severity error
+ * @id python/regex-injection
+ * @tags security
+ * external/cwe/cwe-730
+ * external/cwe/cwe-400
+ */
+
+// determine precision above
+import python
+import semmle.python.security.dataflow.RegexInjection
+import DataFlow::PathGraph
+
+from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
+where config.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
+ sink.getNode(), "This", source.getNode(), "user-provided value"
diff --git a/python/ql/src/experimental/Security/CWE-730/tests/re_bad.py b/python/ql/src/Security/CWE-730/re_bad.py
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/tests/re_bad.py
rename to python/ql/src/Security/CWE-730/re_bad.py
diff --git a/python/ql/src/experimental/Security/CWE-730/tests/re_good.py b/python/ql/src/Security/CWE-730/re_good.py
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/tests/re_good.py
rename to python/ql/src/Security/CWE-730/re_good.py
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
deleted file mode 100644
index d35b596c045..00000000000
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * @name Regular expression injection
- * @description User input should not be used in regular expressions without first being escaped,
- * otherwise a malicious user may be able to inject an expression that could require
- * exponential time on certain inputs.
- * @kind path-problem
- * @problem.severity error
- * @id python/regex-injection
- * @tags security
- * external/cwe/cwe-730
- * external/cwe/cwe-400
- */
-
-// determine precision above
-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 semmle.python.ApiGraphs
-import DataFlow::PathGraph
-
-// Should this be moved to a different structure? (For other queries to be able to use it)
-class ReMethods extends string {
- ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
-}
-
-class DirectRegex extends DataFlow::Node {
- DirectRegex() {
- exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
- reCall = API::moduleImport("re").getMember(reMethod).getACall() and
- this = reCall.getArg(0)
- )
- }
-}
-
-class CompiledRegex extends DataFlow::Node {
- CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
- patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.getObject().getALocalSource() and
- reMethod.getAttributeName() instanceof ReMethods and
- this = patternCall.getArg(0)
- )
- }
-}
-
-class RegexInjectionSink extends DataFlow::Node {
- RegexInjectionSink() { 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 RegexInjectionFlowConfig extends TaintTracking::Configuration {
- RegexInjectionFlowConfig() { this = "RegexInjectionFlowConfig" }
-
- override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink }
-
- override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof EscapeSanitizer }
-}
-
-from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
- sink.getNode(), "This", source.getNode(), "user-provided value"
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index 4be00ba5bf9..f58f6317e1e 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -9,6 +9,7 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Frameworks
+private import semmle.python.ApiGraphs
/**
* A data-flow node that executes an operating system command,
@@ -625,5 +626,47 @@ module Cryptography {
final override int minimumSecureKeySize() { result = 224 }
}
}
+/*
+ */
+
+class ReMethods extends string {
+ ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
+}
+
+class DirectRegex extends DataFlow::Node {
+ DirectRegex() {
+ exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
+ reCall = API::moduleImport("re").getMember(reMethod).getACall() and
+ this = reCall.getArg(0)
+ )
+ }
+}
+
+class CompiledRegex extends DataFlow::Node {
+ CompiledRegex() {
+ exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ patternCall = API::moduleImport("re").getMember("compile").getACall() and
+ patternCall = reMethod.getObject().getALocalSource() and
+ reMethod.getAttributeName() instanceof ReMethods and
+ this = patternCall.getArg(0)
+ )
+ }
+}
+
+class RegexExecution extends DataFlow::Node {
+ RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex }
+}
+
+// pending refactor if needed
+class RegexEscape extends DataFlow::Node {
+ RegexEscape() {
+ 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
+ )
}
}
diff --git a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
new file mode 100644
index 00000000000..5a8f386a781
--- /dev/null
+++ b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
@@ -0,0 +1,23 @@
+/**
+ * Provides a taint-tracking configuration for detecting regular expression injections
+ * vulnerabilities.
+ */
+
+import python
+import semmle.python.Concepts
+import semmle.python.dataflow.new.DataFlow
+import semmle.python.dataflow.new.TaintTracking
+import semmle.python.dataflow.new.RemoteFlowSources
+
+/**
+ * A taint-tracking configuration for detecting regular expression injections.
+ */
+class RegexInjectionFlowConfig extends TaintTracking::Configuration {
+ RegexInjectionFlowConfig() { this = "RegexInjectionFlowConfig" }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof RegexExecution }
+
+ override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof RegexEscape }
+}
From e4736d064e525ca51cdb52df1fedcdb54b0b8b04 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 18 Mar 2021 23:36:54 +0100
Subject: [PATCH 029/168] Typo
---
.../ql/src/semmle/python/security/dataflow/RegexInjection.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
index 5a8f386a781..968010dd9a0 100644
--- a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
+++ b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
@@ -1,5 +1,5 @@
/**
- * Provides a taint-tracking configuration for detecting regular expression injections
+ * Provides a taint-tracking configuration for detecting regular expression injection
* vulnerabilities.
*/
From a1b5cc3bc61860e50449617a8c79a9bfa975b3bd Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 19 Mar 2021 01:26:21 +0100
Subject: [PATCH 030/168] Typo
---
python/ql/src/Security/CWE-730/RegexInjection.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/Security/CWE-730/RegexInjection.qhelp
index 002cbcef0a8..2e3d238daa4 100644
--- a/python/ql/src/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/Security/CWE-730/RegexInjection.qhelp
@@ -2,7 +2,7 @@
-
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.
+
If a regular expression is built by a not escaped user-provided value, a user is likely to be able to cause a Denial of Service.
From 6d5a0f2f842b1f7a459a2e8e5d54c67fc86516c7 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 19 Mar 2021 01:34:13 +0100
Subject: [PATCH 031/168] Limit Sanitizer to re.escape(arg)
---
python/ql/src/semmle/python/Concepts.qll | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index f58f6317e1e..60880794845 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -657,16 +657,8 @@ class RegexExecution extends DataFlow::Node {
RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex }
}
-// pending refactor if needed
class RegexEscape extends DataFlow::Node {
RegexEscape() {
- 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
- )
+ this = API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
}
}
From caaf5436c6a4ed8a32c0b4f43a1418052a4b7ba5 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 19 Mar 2021 01:51:59 +0100
Subject: [PATCH 032/168] Attempt to restructuring ReMethods and
RegexExecution's modules
---
python/ql/src/semmle/python/Concepts.qll | 2 +-
.../src/semmle/python/frameworks/Stdlib.qll | 30 +++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index 60880794845..751f9f0a302 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -654,7 +654,7 @@ class CompiledRegex extends DataFlow::Node {
}
class RegexExecution extends DataFlow::Node {
- RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex }
+ RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex } // How should this be cross-imported with Stdlib?
}
class RegexEscape extends DataFlow::Node {
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index 01df130d0db..c074e6fe1cd 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -864,6 +864,36 @@ private module Stdlib {
class Sqlite3 extends PEP249ModuleApiNode {
Sqlite3() { this = API::moduleImport("sqlite3") }
}
+
+ // ---------------------------------------------------------------------------
+ // re
+ // ---------------------------------------------------------------------------
+ /** List of re methods. */
+ private class ReMethods extends string {
+ ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
+ }
+
+ /** re.ReMethod(pattern, string) */
+ private class DirectRegex extends DataFlow::Node {
+ DirectRegex() {
+ exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
+ reCall = API::moduleImport("re").getMember(reMethod).getACall() and
+ this = reCall.getArg(0)
+ )
+ }
+ }
+
+ /** re.compile(pattern).ReMethod */
+ class CompiledRegex extends DataFlow::Node {
+ CompiledRegex() {
+ exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ patternCall = API::moduleImport("re").getMember("compile").getACall() and
+ patternCall = reMethod.getObject().getALocalSource() and
+ reMethod.getAttributeName() instanceof ReMethods and
+ this = patternCall.getArg(0)
+ )
+ }
+ }
}
// ---------------------------------------------------------------------------
From 3daec8e6a27a0776220ca52fe28e184717e1fc50 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 19 Mar 2021 17:46:32 +0100
Subject: [PATCH 033/168] Enclose Sinks and ReMethods in a module
---
.../src/semmle/python/frameworks/Stdlib.qll | 46 ++++++++++---------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index c074e6fe1cd..f9949560d68 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -868,30 +868,32 @@ private module Stdlib {
// ---------------------------------------------------------------------------
// re
// ---------------------------------------------------------------------------
- /** List of re methods. */
- private class ReMethods extends string {
- ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
- }
-
- /** re.ReMethod(pattern, string) */
- private class DirectRegex extends DataFlow::Node {
- DirectRegex() {
- exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
- reCall = API::moduleImport("re").getMember(reMethod).getACall() and
- this = reCall.getArg(0)
- )
+ private module Re {
+ /** List of re methods. */
+ private class ReMethods extends string {
+ ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
}
- }
- /** re.compile(pattern).ReMethod */
- class CompiledRegex extends DataFlow::Node {
- CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
- patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.getObject().getALocalSource() and
- reMethod.getAttributeName() instanceof ReMethods and
- this = patternCall.getArg(0)
- )
+ /** re.ReMethod(pattern, string) */
+ private class DirectRegex extends DataFlow::Node {
+ DirectRegex() {
+ exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
+ reCall = API::moduleImport("re").getMember(reMethod).getACall() and
+ this = reCall.getArg(0)
+ )
+ }
+ }
+
+ /** re.compile(pattern).ReMethod */
+ class CompiledRegex extends DataFlow::Node {
+ CompiledRegex() {
+ exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ patternCall = API::moduleImport("re").getMember("compile").getACall() and
+ patternCall = reMethod.getObject().getALocalSource() and
+ reMethod.getAttributeName() instanceof ReMethods and
+ this = patternCall.getArg(0)
+ )
+ }
}
}
}
From b207929e0ad280fec73fffb7d4c5d193e01f3e34 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 19 Mar 2021 18:07:39 +0100
Subject: [PATCH 034/168] RegexExecution restructuring
---
python/ql/src/semmle/python/Concepts.qll | 18 +++++++++++++++---
.../ql/src/semmle/python/frameworks/Stdlib.qll | 9 ++++++++-
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index 751f9f0a302..aa0c748c1da 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -656,9 +656,21 @@ class CompiledRegex extends DataFlow::Node {
class RegexExecution extends DataFlow::Node {
RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex } // How should this be cross-imported with Stdlib?
}
+/*
+ */
-class RegexEscape extends DataFlow::Node {
- RegexEscape() {
- this = API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
+module RegexExecution {
+ abstract class Range extends DataFlow::Node {
+ DataFlow::Node getRegexNode() {
+ result instanceof DirectRegex or result instanceof CompiledRegex
+ }
}
}
+
+class RegexExecution extends DataFlow::Node {
+ override RegexExecution::Range range;
+
+ RegexExecution() { this = range }
+
+ DataFlow::Node getRegexNode() { result = range.getRegexNode() }
+}
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index f9949560d68..ed5a56be931 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -885,7 +885,7 @@ private module Stdlib {
}
/** re.compile(pattern).ReMethod */
- class CompiledRegex extends DataFlow::Node {
+ private class CompiledRegex extends DataFlow::Node {
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
patternCall = API::moduleImport("re").getMember("compile").getACall() and
@@ -895,6 +895,13 @@ private module Stdlib {
)
}
}
+
+ private class RegexEscape extends Concepts::RegexExecution {
+ RegexEscape() {
+ this =
+ API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
+ }
+ }
}
}
From 249e4097e3a2faaa7b10914ba01b99a39d2c8f65 Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Mon, 22 Mar 2021 15:12:12 +0100
Subject: [PATCH 035/168] Change query ID
Co-authored-by: Rasmus Wriedt Larsen
---
python/ql/src/Security/CWE-730/RegexInjection.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql
index 27bbe69529d..3baa3b54bea 100644
--- a/python/ql/src/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/Security/CWE-730/RegexInjection.ql
@@ -5,7 +5,7 @@
* exponential time on certain inputs.
* @kind path-problem
* @problem.severity error
- * @id python/regex-injection
+ * @id py/regex-injection
* @tags security
* external/cwe/cwe-730
* external/cwe/cwe-400
From b27b77c38fda588586bd1ea3a0e942a5f4e403f8 Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Mon, 22 Mar 2021 15:30:54 +0100
Subject: [PATCH 036/168] Apply suggestions from code review
Co-authored-by: yoff
---
python/ql/src/semmle/python/Concepts.qll | 4 +---
python/ql/src/semmle/python/frameworks/Stdlib.qll | 6 +++---
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index aa0c748c1da..497ea0c0e31 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -661,9 +661,7 @@ class RegexExecution extends DataFlow::Node {
module RegexExecution {
abstract class Range extends DataFlow::Node {
- DataFlow::Node getRegexNode() {
- result instanceof DirectRegex or result instanceof CompiledRegex
- }
+ abstract DataFlow::Node getRegexNode();
}
}
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index ed5a56be931..c40ac53f8e4 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -875,7 +875,7 @@ private module Stdlib {
}
/** re.ReMethod(pattern, string) */
- private class DirectRegex extends DataFlow::Node {
+ private class DirectRegex extends RegexExecution::Range {
DirectRegex() {
exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
reCall = API::moduleImport("re").getMember(reMethod).getACall() and
@@ -885,7 +885,7 @@ private module Stdlib {
}
/** re.compile(pattern).ReMethod */
- private class CompiledRegex extends DataFlow::Node {
+ private class CompiledRegex extends RegexExecution::Range {
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
patternCall = API::moduleImport("re").getMember("compile").getACall() and
@@ -896,7 +896,7 @@ private module Stdlib {
}
}
- private class RegexEscape extends Concepts::RegexExecution {
+ private class RegexEscape extends DataFlow::Node {
RegexEscape() {
this =
API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
From 0f20eeb395645b2185528b832a6f56ba039b0552 Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Wed, 24 Mar 2021 09:34:04 +0100
Subject: [PATCH 037/168] Apply suggestions
Co-authored-by: yoff
---
python/ql/src/semmle/python/Concepts.qll | 2 +-
.../src/semmle/python/frameworks/Stdlib.qll | 21 ++++++++++++-------
.../security/dataflow/RegexInjection.qll | 7 +++++--
3 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index 497ea0c0e31..d2defca27a1 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -666,7 +666,7 @@ module RegexExecution {
}
class RegexExecution extends DataFlow::Node {
- override RegexExecution::Range range;
+ RegexExecution::Range range;
RegexExecution() { this = range }
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index c40ac53f8e4..c86e4cf2e22 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -875,25 +875,32 @@ private module Stdlib {
}
/** re.ReMethod(pattern, string) */
- private class DirectRegex extends RegexExecution::Range {
+ private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+
DirectRegex() {
- exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
- reCall = API::moduleImport("re").getMember(reMethod).getACall() and
- this = reCall.getArg(0)
- )
+ this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
+ regexNode = this.getArg(0)
}
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
}
/** re.compile(pattern).ReMethod */
- private class CompiledRegex extends RegexExecution::Range {
+ private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
reMethod.getAttributeName() instanceof ReMethods and
- this = patternCall.getArg(0)
+ regexNode = patternCall.getArg(0)
)
}
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
}
private class RegexEscape extends DataFlow::Node {
diff --git a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
index 968010dd9a0..2758db37d65 100644
--- a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
+++ b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
@@ -17,7 +17,10 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSink(DataFlow::Node sink) { sink instanceof RegexExecution }
+ override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
- override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof RegexEscape }
+ override predicate isSanitizer(DataFlow::Node sanitizer) {
+ sanitizer =
+ API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
+ }
}
From 444a15a461ee8f99428650daa2ae6d95f7eb25b1 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 10:00:10 +0100
Subject: [PATCH 038/168] Polish imports
---
python/ql/src/semmle/python/Concepts.qll | 1 -
python/ql/src/semmle/python/security/dataflow/RegexInjection.qll | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index d2defca27a1..cc2e4ac3ca7 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -9,7 +9,6 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Frameworks
-private import semmle.python.ApiGraphs
/**
* A data-flow node that executes an operating system command,
diff --git a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
index 2758db37d65..98545816c82 100644
--- a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
+++ b/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
@@ -8,6 +8,7 @@ import semmle.python.Concepts
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
+import semmle.python.ApiGraphs
/**
* A taint-tracking configuration for detecting regular expression injections.
From 28fdeba4fafc4ab0b7cff4cb1307fff3298440b8 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 17:59:48 +0100
Subject: [PATCH 039/168] Structure development
---
.../Security/CWE-730/RegexInjection.qhelp | 0
.../Security/CWE-730/RegexInjection.ql | 4 +-
.../Security/CWE-730/re_bad.py | 0
.../Security/CWE-730/re_good.py | 0
.../experimental/semmle/python/Concepts.qll | 29 +++
.../semmle/python/frameworks/Stdlib.qll | 232 +++++++++++++++++-
.../security/injection}/RegexInjection.qll | 2 +-
python/ql/src/semmle/python/Concepts.qll | 46 +---
.../src/semmle/python/frameworks/Stdlib.qll | 46 ----
9 files changed, 264 insertions(+), 95 deletions(-)
rename python/ql/src/{ => experimental}/Security/CWE-730/RegexInjection.qhelp (100%)
rename python/ql/src/{ => experimental}/Security/CWE-730/RegexInjection.ql (92%)
rename python/ql/src/{ => experimental}/Security/CWE-730/re_bad.py (100%)
rename python/ql/src/{ => experimental}/Security/CWE-730/re_good.py (100%)
rename python/ql/src/{semmle/python/security/dataflow => experimental/semmle/python/security/injection}/RegexInjection.qll (95%)
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
similarity index 100%
rename from python/ql/src/Security/CWE-730/RegexInjection.qhelp
rename to python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
similarity index 92%
rename from python/ql/src/Security/CWE-730/RegexInjection.ql
rename to python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index 3baa3b54bea..ccb97fbee54 100644
--- a/python/ql/src/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -13,10 +13,10 @@
// determine precision above
import python
-import semmle.python.security.dataflow.RegexInjection
+import experimental.semmle.python.security.injection.RegexInjection
import DataFlow::PathGraph
from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
- sink.getNode(), "This", source.getNode(), "user-provided value"
+ sink.getNode(), "This", source.getNode(), "user-provided value"
\ No newline at end of file
diff --git a/python/ql/src/Security/CWE-730/re_bad.py b/python/ql/src/experimental/Security/CWE-730/re_bad.py
similarity index 100%
rename from python/ql/src/Security/CWE-730/re_bad.py
rename to python/ql/src/experimental/Security/CWE-730/re_bad.py
diff --git a/python/ql/src/Security/CWE-730/re_good.py b/python/ql/src/experimental/Security/CWE-730/re_good.py
similarity index 100%
rename from python/ql/src/Security/CWE-730/re_good.py
rename to python/ql/src/experimental/Security/CWE-730/re_good.py
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 904b7967ee8..172a7fc2003 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -13,3 +13,32 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import experimental.semmle.python.Frameworks
+
+/** Provides classes for modeling Regular Expression-related APIs. */
+module RegexExecution {
+ /**
+ * A data-flow node that works with regular expressions.
+ *
+ * Extend this class to model new APIs. If you want to refine existing API models,
+ * extend `RegexExecution` instead.
+ */
+ abstract class Range extends DataFlow::Node {
+ abstract DataFlow::Node getRegexNode();
+ abstract Attribute getRegexMethod();
+ }
+}
+
+/**
+ * A data-flow node that works with regular expressions.
+ *
+ * Extend this class to refine existing API models. If you want to model new APIs,
+ * extend `RegexExecution::Range` instead.
+ */
+class RegexExecution extends DataFlow::Node {
+ RegexExecution::Range range;
+
+ RegexExecution() { this = range }
+
+ DataFlow::Node getRegexNode() { result = range.getRegexNode() }
+ Attribute getRegexMethod() { result = range.getRegexMethod() }
+}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 420caf0d73b..edaa42fad8a 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -8,4 +8,234 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.dataflow.new.RemoteFlowSources
private import experimental.semmle.python.Concepts
-private import semmle.python.ApiGraphs
+
+/** Provides models for the Python standard library. */
+private module Stdlib {
+ // ---------------------------------------------------------------------------
+ // re
+ // ---------------------------------------------------------------------------
+ private module Re {
+
+ /** Gets a reference to the `re` module. */
+ private DataFlow::Node re(DataFlow::TypeTracker t) {
+ t.start() and
+ result = DataFlow::importNode("re")
+ or
+ exists(DataFlow::TypeTracker t2 | result = re(t2).track(t2, t))
+ }
+
+ /** Gets a reference to the `re` module. */
+ DataFlow::Node re() { result = re(DataFlow::TypeTracker::end()) }
+
+ /**
+ * Gets a reference to the attribute `attr_name` of the `re` module.
+ * WARNING: Only holds for a few predefined attributes.
+ */
+ private DataFlow::Node re_attr(DataFlow::TypeTracker t, string attr_name) {
+ attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile"] and
+ (
+ t.start() and
+ result = DataFlow::importNode("re" + "." + attr_name)
+ or
+ t.startInAttr(attr_name) and
+ result = re()
+ )
+ or
+ // Due to bad performance when using normal setup with `re_attr(t2, attr_name).track(t2, t)`
+ // we have inlined that code and forced a join
+ exists(DataFlow::TypeTracker t2 |
+ exists(DataFlow::StepSummary summary |
+ re_attr_first_join(t2, attr_name, result, summary) and
+ t = t2.append(summary)
+ )
+ )
+ }
+
+ pragma[nomagic]
+ private predicate re_attr_first_join(
+ DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
+ ) {
+ DataFlow::StepSummary::step(re_attr(t2, attr_name), res, summary)
+ }
+
+ /**
+ * Gets a reference to the attribute `attr_name` of the `re` module.
+ * WARNING: Only holds for a few predefined attributes.
+ */
+ private DataFlow::Node re_attr(string attr_name) {
+ result = re_attr(DataFlow::TypeTracker::end(), attr_name)
+ }
+
+ /**
+ * Gets a reference to any `attr_name` of the `re` module that immediately executes an expression.
+ * WARNING: Only holds for a few predefined attributes.
+ */
+ private DataFlow::Node re_exec_attr() {
+ exists(string attr_name |
+ attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] and
+ result = re_attr(DataFlow::TypeTracker::end(), attr_name)
+ )
+ }
+
+ /**
+ * A call to `re.match`
+ * See https://docs.python.org/3/library/re.html#re.match
+ */
+ private class ReMatchCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReMatchCall() { node.getFunction() = re_attr("match").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.fullmatch`
+ * See https://docs.python.org/3/library/re.html#re.fullmatch
+ */
+ private class ReFullMatchCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReFullMatchCall() { node.getFunction() = re_attr("fullmatch").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.search`
+ * See https://docs.python.org/3/library/re.html#re.search
+ */
+ private class ReSearchCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReSearchCall() { node.getFunction() = re_attr("search").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.split`
+ * See https://docs.python.org/3/library/re.html#re.split
+ */
+ private class ReSplitCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReSplitCall() { node.getFunction() = re_attr("split").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.findall`
+ * See https://docs.python.org/3/library/re.html#re.findall
+ */
+ private class ReFindAllCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReFindAllCall() { node.getFunction() = re_attr("findall").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.finditer`
+ * See https://docs.python.org/3/library/re.html#re.finditer
+ */
+ private class ReFindIterCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReFindIterCall() { node.getFunction() = re_attr("finditer").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.sub`
+ * See https://docs.python.org/3/library/re.html#re.sub
+ */
+ private class ReSubCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReSubCall() { node.getFunction() = re_attr("sub").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.subn`
+ * See https://docs.python.org/3/library/re.html#re.subn
+ */
+ private class ReSubNCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReSubNCall() { node.getFunction() = re_attr("subn").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
+ /**
+ * A call to `re.compile`
+ * See https://docs.python.org/3/library/re.html#re.match
+ */
+ private class ReCompileCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReCompileCall() { node.getFunction() = re_attr("compile").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() {
+ exists (DataFlow::AttrRead reMethod |
+ reMethod = re_exec_attr() and
+ node.getFunction() = reMethod.getObject().getALocalSource().asCfgNode() and
+ result = reMethod.asExpr().(Attribute)
+ )
+ }
+ }
+
+ /**
+ * A class for modeling expressions immediately executing a regular expression.
+ * See `re_exec_attr()`
+ */
+ private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+ Attribute regexMethod;
+
+ DirectRegex() {
+ // needs inheritance (?)
+ this = re_exec_attr() and regexNode = this.getRegexNode() and regexMethod = this.getRegexMethod()
+ }
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
+ override Attribute getRegexMethod() { result = regexMethod }
+ }
+
+ /**
+ * A class for finding `ReCompileCall` whose `Attribute` is an instance of `DirectRegex`.
+ * See `ReCompileCall`, `DirectRegex`, `re_exec_attr()`
+ */
+ private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+ Attribute regexMethod;
+
+ CompiledRegex() {
+ exists(DirectRegex reMethod, ReCompileCall compileCall |
+ this = reMethod and
+ reMethod.getRegexMethod() = compileCall.getRegexMethod() and
+ regexNode = compileCall.getRegexNode() and
+ regexMethod = reMethod.getRegexMethod()
+ )
+ }
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
+ override Attribute getRegexMethod() { result = regexMethod }
+ }
+ }
+}
\ No newline at end of file
diff --git a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
similarity index 95%
rename from python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
rename to python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 98545816c82..5e2cc684b43 100644
--- a/python/ql/src/semmle/python/security/dataflow/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -4,7 +4,7 @@
*/
import python
-import semmle.python.Concepts
+import experimental.semmle.python.Concepts
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index cc2e4ac3ca7..ccae7251a2c 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -625,49 +625,5 @@ module Cryptography {
final override int minimumSecureKeySize() { result = 224 }
}
}
-/*
- */
-
-class ReMethods extends string {
- ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
-}
-
-class DirectRegex extends DataFlow::Node {
- DirectRegex() {
- exists(ReMethods reMethod, DataFlow::CallCfgNode reCall |
- reCall = API::moduleImport("re").getMember(reMethod).getACall() and
- this = reCall.getArg(0)
- )
}
-}
-
-class CompiledRegex extends DataFlow::Node {
- CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
- patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.getObject().getALocalSource() and
- reMethod.getAttributeName() instanceof ReMethods and
- this = patternCall.getArg(0)
- )
- }
-}
-
-class RegexExecution extends DataFlow::Node {
- RegexExecution() { this instanceof DirectRegex or this instanceof CompiledRegex } // How should this be cross-imported with Stdlib?
-}
-/*
- */
-
-module RegexExecution {
- abstract class Range extends DataFlow::Node {
- abstract DataFlow::Node getRegexNode();
- }
-}
-
-class RegexExecution extends DataFlow::Node {
- RegexExecution::Range range;
-
- RegexExecution() { this = range }
-
- DataFlow::Node getRegexNode() { result = range.getRegexNode() }
-}
+}
\ No newline at end of file
diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll
index c86e4cf2e22..01df130d0db 100644
--- a/python/ql/src/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll
@@ -864,52 +864,6 @@ private module Stdlib {
class Sqlite3 extends PEP249ModuleApiNode {
Sqlite3() { this = API::moduleImport("sqlite3") }
}
-
- // ---------------------------------------------------------------------------
- // re
- // ---------------------------------------------------------------------------
- private module Re {
- /** List of re methods. */
- private class ReMethods extends string {
- ReMethods() { this in ["match", "fullmatch", "search", "split", "findall", "finditer"] }
- }
-
- /** re.ReMethod(pattern, string) */
- private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
- DataFlow::Node regexNode;
-
- DirectRegex() {
- this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
- regexNode = this.getArg(0)
- }
-
- override DataFlow::Node getRegexNode() { result = regexNode }
- }
-
- /** re.compile(pattern).ReMethod */
- private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
- DataFlow::Node regexNode;
-
- CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
- this.getFunction() = reMethod and
- patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.getObject().getALocalSource() and
- reMethod.getAttributeName() instanceof ReMethods and
- regexNode = patternCall.getArg(0)
- )
- }
-
- override DataFlow::Node getRegexNode() { result = regexNode }
- }
-
- private class RegexEscape extends DataFlow::Node {
- RegexEscape() {
- this =
- API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
- }
- }
- }
}
// ---------------------------------------------------------------------------
From a1a3c98d92fa433d642139a3e259713a31cc2c3e Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 18:16:36 +0100
Subject: [PATCH 040/168] Undo main Concepts.qll change
---
python/ql/src/semmle/python/Concepts.qll | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index ccae7251a2c..2706a497f9a 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -625,5 +625,4 @@ module Cryptography {
final override int minimumSecureKeySize() { result = 224 }
}
}
- }
-}
\ No newline at end of file
+ }
\ No newline at end of file
From d61adccd3c6b6511e106b106bfe2d6efef612c14 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 18:23:59 +0100
Subject: [PATCH 041/168] Take main Concepts.qll out of the PR
---
python/ql/src/semmle/python/Concepts.qll | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/src/semmle/python/Concepts.qll
index 2706a497f9a..4be00ba5bf9 100644
--- a/python/ql/src/semmle/python/Concepts.qll
+++ b/python/ql/src/semmle/python/Concepts.qll
@@ -625,4 +625,5 @@ module Cryptography {
final override int minimumSecureKeySize() { result = 224 }
}
}
- }
\ No newline at end of file
+ }
+}
From b5ea41fcca6d80ddeaa7209a8f7f0edaef5237f8 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 21:02:09 +0100
Subject: [PATCH 042/168] Fix CompiledRegex
---
.../src/experimental/semmle/python/frameworks/Stdlib.qll | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index edaa42fad8a..a6d848cc126 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -226,11 +226,10 @@ private module Stdlib {
Attribute regexMethod;
CompiledRegex() {
- exists(DirectRegex reMethod, ReCompileCall compileCall |
- this = reMethod and
- reMethod.getRegexMethod() = compileCall.getRegexMethod() and
+ exists(ReCompileCall compileCall |
regexNode = compileCall.getRegexNode() and
- regexMethod = reMethod.getRegexMethod()
+ regexMethod = compileCall.getRegexMethod() and
+ this = compileCall
)
}
From ce23db2e9ca80497f71b7c9792f60582906db42b Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Wed, 24 Mar 2021 21:11:45 +0100
Subject: [PATCH 043/168] Move Sanitizer to ReEscapeCall
---
.../semmle/python/frameworks/Stdlib.qll | 15 ++++++++++++++-
.../python/security/injection/RegexInjection.qll | 8 +++-----
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index a6d848cc126..d243eacd3d0 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -32,7 +32,7 @@ private module Stdlib {
* WARNING: Only holds for a few predefined attributes.
*/
private DataFlow::Node re_attr(DataFlow::TypeTracker t, string attr_name) {
- attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile"] and
+ attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile", "escape"] and
(
t.start() and
result = DataFlow::importNode("re" + "." + attr_name)
@@ -181,6 +181,19 @@ private module Stdlib {
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
+ /**
+ * A call to `re.escape`
+ * See https://docs.python.org/3/library/re.html#re.escape
+ */
+ private class ReEscapeCall extends RegexExecution::Range, DataFlow::CfgNode {
+ override CallNode node;
+
+ ReEscapeCall() { node.getFunction() = re_attr("escape").asCfgNode() }
+
+ override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+ override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
+ }
+
/**
* A call to `re.compile`
* See https://docs.python.org/3/library/re.html#re.match
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 5e2cc684b43..0d42acbac49 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -5,6 +5,7 @@
import python
import experimental.semmle.python.Concepts
+import experimental.semmle.python.frameworks.Stdlib
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
@@ -18,10 +19,7 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
+ override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
- override predicate isSanitizer(DataFlow::Node sanitizer) {
- sanitizer =
- API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
- }
+ override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof ReEscapeCall }
}
From ee1d2b645b0a42a370c6c47fb721ecff3562b348 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 25 Mar 2021 18:19:11 +0100
Subject: [PATCH 044/168] Delete DirectRegex and CompiledRegex
---
.../semmle/python/frameworks/Stdlib.qll | 37 -------------------
1 file changed, 37 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index d243eacd3d0..fab8debb1b8 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -212,42 +212,5 @@ private module Stdlib {
)
}
}
-
- /**
- * A class for modeling expressions immediately executing a regular expression.
- * See `re_exec_attr()`
- */
- private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
- DataFlow::Node regexNode;
- Attribute regexMethod;
-
- DirectRegex() {
- // needs inheritance (?)
- this = re_exec_attr() and regexNode = this.getRegexNode() and regexMethod = this.getRegexMethod()
- }
-
- override DataFlow::Node getRegexNode() { result = regexNode }
- override Attribute getRegexMethod() { result = regexMethod }
- }
-
- /**
- * A class for finding `ReCompileCall` whose `Attribute` is an instance of `DirectRegex`.
- * See `ReCompileCall`, `DirectRegex`, `re_exec_attr()`
- */
- private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
- DataFlow::Node regexNode;
- Attribute regexMethod;
-
- CompiledRegex() {
- exists(ReCompileCall compileCall |
- regexNode = compileCall.getRegexNode() and
- regexMethod = compileCall.getRegexMethod() and
- this = compileCall
- )
- }
-
- override DataFlow::Node getRegexNode() { result = regexNode }
- override Attribute getRegexMethod() { result = regexMethod }
- }
}
}
\ No newline at end of file
From 30554a16da55ef9d652ad60e6437593682b07c23 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 25 Mar 2021 18:20:13 +0100
Subject: [PATCH 045/168] Format
---
.../Security/CWE-730/RegexInjection.ql | 2 +-
.../semmle/python/frameworks/Stdlib.qll | 24 ++++++++++++++-----
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index ccb97fbee54..9d3da12f9bd 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -19,4 +19,4 @@ import DataFlow::PathGraph
from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
- sink.getNode(), "This", source.getNode(), "user-provided value"
\ No newline at end of file
+ sink.getNode(), "This", source.getNode(), "user-provided value"
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index fab8debb1b8..4b5f8f63f6a 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -15,7 +15,6 @@ private module Stdlib {
// re
// ---------------------------------------------------------------------------
private module Re {
-
/** Gets a reference to the `re` module. */
private DataFlow::Node re(DataFlow::TypeTracker t) {
t.start() and
@@ -32,7 +31,10 @@ private module Stdlib {
* WARNING: Only holds for a few predefined attributes.
*/
private DataFlow::Node re_attr(DataFlow::TypeTracker t, string attr_name) {
- attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile", "escape"] and
+ attr_name in [
+ "match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile",
+ "escape"
+ ] and
(
t.start() and
result = DataFlow::importNode("re" + "." + attr_name)
@@ -87,6 +89,7 @@ private module Stdlib {
ReMatchCall() { node.getFunction() = re_attr("match").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -100,6 +103,7 @@ private module Stdlib {
ReFullMatchCall() { node.getFunction() = re_attr("fullmatch").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -113,6 +117,7 @@ private module Stdlib {
ReSearchCall() { node.getFunction() = re_attr("search").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -126,6 +131,7 @@ private module Stdlib {
ReSplitCall() { node.getFunction() = re_attr("split").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -139,6 +145,7 @@ private module Stdlib {
ReFindAllCall() { node.getFunction() = re_attr("findall").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -152,6 +159,7 @@ private module Stdlib {
ReFindIterCall() { node.getFunction() = re_attr("finditer").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -165,6 +173,7 @@ private module Stdlib {
ReSubCall() { node.getFunction() = re_attr("sub").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -178,6 +187,7 @@ private module Stdlib {
ReSubNCall() { node.getFunction() = re_attr("subn").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -191,6 +201,7 @@ private module Stdlib {
ReEscapeCall() { node.getFunction() = re_attr("escape").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
+
override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
}
@@ -204,13 +215,14 @@ private module Stdlib {
ReCompileCall() { node.getFunction() = re_attr("compile").asCfgNode() }
override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
- override Attribute getRegexMethod() {
- exists (DataFlow::AttrRead reMethod |
+
+ override Attribute getRegexMethod() {
+ exists(DataFlow::AttrRead reMethod |
reMethod = re_exec_attr() and
node.getFunction() = reMethod.getObject().getALocalSource().asCfgNode() and
result = reMethod.asExpr().(Attribute)
)
- }
+ }
}
}
-}
\ No newline at end of file
+}
From 3d990c595097c4af80392cc0ac26988605d2f059 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 10:05:50 +0100
Subject: [PATCH 046/168] Get back to ApiGraphs
---
.../experimental/semmle/python/Concepts.qll | 9 +
.../semmle/python/frameworks/Stdlib.qll | 254 +++---------------
.../security/injection/RegexInjection.qll | 3 +-
3 files changed, 51 insertions(+), 215 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 172a7fc2003..8a88ffb2154 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -13,6 +13,7 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import experimental.semmle.python.Frameworks
+private import semmle.python.ApiGraphs
/** Provides classes for modeling Regular Expression-related APIs. */
module RegexExecution {
@@ -24,6 +25,7 @@ module RegexExecution {
*/
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
+
abstract Attribute getRegexMethod();
}
}
@@ -40,5 +42,12 @@ class RegexExecution extends DataFlow::Node {
RegexExecution() { this = range }
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
+
Attribute getRegexMethod() { result = range.getRegexMethod() }
}
+
+class RegexEscape extends DataFlow::Node {
+ RegexEscape() {
+ this = API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
+ }
+}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 4b5f8f63f6a..5a3441bed83 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -8,221 +8,49 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.dataflow.new.RemoteFlowSources
private import experimental.semmle.python.Concepts
+private import semmle.python.ApiGraphs
/** Provides models for the Python standard library. */
-private module Stdlib {
- // ---------------------------------------------------------------------------
- // re
- // ---------------------------------------------------------------------------
- private module Re {
- /** Gets a reference to the `re` module. */
- private DataFlow::Node re(DataFlow::TypeTracker t) {
- t.start() and
- result = DataFlow::importNode("re")
- or
- exists(DataFlow::TypeTracker t2 | result = re(t2).track(t2, t))
- }
-
- /** Gets a reference to the `re` module. */
- DataFlow::Node re() { result = re(DataFlow::TypeTracker::end()) }
-
- /**
- * Gets a reference to the attribute `attr_name` of the `re` module.
- * WARNING: Only holds for a few predefined attributes.
- */
- private DataFlow::Node re_attr(DataFlow::TypeTracker t, string attr_name) {
- attr_name in [
- "match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn", "compile",
- "escape"
- ] and
- (
- t.start() and
- result = DataFlow::importNode("re" + "." + attr_name)
- or
- t.startInAttr(attr_name) and
- result = re()
- )
- or
- // Due to bad performance when using normal setup with `re_attr(t2, attr_name).track(t2, t)`
- // we have inlined that code and forced a join
- exists(DataFlow::TypeTracker t2 |
- exists(DataFlow::StepSummary summary |
- re_attr_first_join(t2, attr_name, result, summary) and
- t = t2.append(summary)
- )
- )
- }
-
- pragma[nomagic]
- private predicate re_attr_first_join(
- DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary
- ) {
- DataFlow::StepSummary::step(re_attr(t2, attr_name), res, summary)
- }
-
- /**
- * Gets a reference to the attribute `attr_name` of the `re` module.
- * WARNING: Only holds for a few predefined attributes.
- */
- private DataFlow::Node re_attr(string attr_name) {
- result = re_attr(DataFlow::TypeTracker::end(), attr_name)
- }
-
- /**
- * Gets a reference to any `attr_name` of the `re` module that immediately executes an expression.
- * WARNING: Only holds for a few predefined attributes.
- */
- private DataFlow::Node re_exec_attr() {
- exists(string attr_name |
- attr_name in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"] and
- result = re_attr(DataFlow::TypeTracker::end(), attr_name)
- )
- }
-
- /**
- * A call to `re.match`
- * See https://docs.python.org/3/library/re.html#re.match
- */
- private class ReMatchCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReMatchCall() { node.getFunction() = re_attr("match").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.fullmatch`
- * See https://docs.python.org/3/library/re.html#re.fullmatch
- */
- private class ReFullMatchCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReFullMatchCall() { node.getFunction() = re_attr("fullmatch").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.search`
- * See https://docs.python.org/3/library/re.html#re.search
- */
- private class ReSearchCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReSearchCall() { node.getFunction() = re_attr("search").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.split`
- * See https://docs.python.org/3/library/re.html#re.split
- */
- private class ReSplitCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReSplitCall() { node.getFunction() = re_attr("split").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.findall`
- * See https://docs.python.org/3/library/re.html#re.findall
- */
- private class ReFindAllCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReFindAllCall() { node.getFunction() = re_attr("findall").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.finditer`
- * See https://docs.python.org/3/library/re.html#re.finditer
- */
- private class ReFindIterCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReFindIterCall() { node.getFunction() = re_attr("finditer").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.sub`
- * See https://docs.python.org/3/library/re.html#re.sub
- */
- private class ReSubCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReSubCall() { node.getFunction() = re_attr("sub").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.subn`
- * See https://docs.python.org/3/library/re.html#re.subn
- */
- private class ReSubNCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReSubNCall() { node.getFunction() = re_attr("subn").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.escape`
- * See https://docs.python.org/3/library/re.html#re.escape
- */
- private class ReEscapeCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReEscapeCall() { node.getFunction() = re_attr("escape").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() { result = node.getNode().getFunc().(Attribute) }
- }
-
- /**
- * A call to `re.compile`
- * See https://docs.python.org/3/library/re.html#re.match
- */
- private class ReCompileCall extends RegexExecution::Range, DataFlow::CfgNode {
- override CallNode node;
-
- ReCompileCall() { node.getFunction() = re_attr("compile").asCfgNode() }
-
- override DataFlow::Node getRegexNode() { result.asCfgNode() = node.getArg(0) }
-
- override Attribute getRegexMethod() {
- exists(DataFlow::AttrRead reMethod |
- reMethod = re_exec_attr() and
- node.getFunction() = reMethod.getObject().getALocalSource().asCfgNode() and
- result = reMethod.asExpr().(Attribute)
- )
- }
+private module Re {
+ /** List of re methods. */
+ private class ReMethods extends string {
+ ReMethods() {
+ this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"]
}
}
+
+ private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+ Attribute regexMethod;
+
+ DirectRegex() {
+ this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
+ regexNode = this.getArg(0) and
+ regexMethod = this.asExpr().(Attribute)
+ }
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
+
+ override Attribute getRegexMethod() { result = regexMethod }
+ }
+
+ private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
+ DataFlow::Node regexNode;
+ Attribute regexMethod;
+
+ CompiledRegex() {
+ exists(DataFlow::CallCfgNode patternCall, DirectRegex reMethod |
+ this = reMethod and
+ patternCall = API::moduleImport("re").getMember("compile").getACall() and
+ patternCall = reMethod.(DataFlow::AttrRead).getObject().getALocalSource() and
+ regexNode = patternCall.getArg(0) and
+ // regexMethod is *not* worked out outside class instanciation because `CompiledRegex` focuses on re.compile(pattern).ReMethod
+ regexMethod = reMethod.getRegexMethod()
+ )
+ }
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
+
+ override Attribute getRegexMethod() { result = regexMethod }
+ }
}
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 0d42acbac49..102fb80cfff 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -5,7 +5,6 @@
import python
import experimental.semmle.python.Concepts
-import experimental.semmle.python.frameworks.Stdlib
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
@@ -21,5 +20,5 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
- override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof ReEscapeCall }
+ override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof RegexEscape }
}
From 805f86a5cf49a81fa47c616064fc88efa12aca12 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 10:15:12 +0100
Subject: [PATCH 047/168] Polish RegexEscape
---
.../ql/src/experimental/semmle/python/Concepts.qll | 13 +++++++++++--
.../python/security/injection/RegexInjection.qll | 4 +++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 8a88ffb2154..b8cef8e4e11 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -46,8 +46,17 @@ class RegexExecution extends DataFlow::Node {
Attribute getRegexMethod() { result = range.getRegexMethod() }
}
-class RegexEscape extends DataFlow::Node {
+class RegexEscape extends DataFlow::CallCfgNode {
+ DataFlow::Node regexNode;
+ Attribute regexMethod;
+
RegexEscape() {
- this = API::moduleImport("re").getMember("escape").getACall().(DataFlow::CallCfgNode).getArg(0)
+ this = API::moduleImport("re").getMember("escape").getACall() and
+ regexNode = this.getArg(0) and
+ regexMethod = this.asExpr().(Attribute)
}
+
+ DataFlow::Node getRegexNode() { result = regexNode }
+
+ Attribute getRegexMethod() { result = regexMethod }
}
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 102fb80cfff..f82af085db0 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -20,5 +20,7 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
- override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof RegexEscape }
+ override predicate isSanitizer(DataFlow::Node sanitizer) {
+ sanitizer = sanitizer.(RegexEscape).getRegexNode()
+ }
}
From be09ffec3fbb31a69265911cad0d09989dfe5446 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 10:24:42 +0100
Subject: [PATCH 048/168] Create RegexEscape Range
---
.../experimental/semmle/python/Concepts.qll | 42 +++++++++++++------
.../semmle/python/frameworks/Stdlib.qll | 15 +++++++
.../security/injection/RegexInjection.qll | 2 +-
3 files changed, 45 insertions(+), 14 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index b8cef8e4e11..b4723c9e99d 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -18,7 +18,7 @@ private import semmle.python.ApiGraphs
/** Provides classes for modeling Regular Expression-related APIs. */
module RegexExecution {
/**
- * A data-flow node that works with regular expressions.
+ * A data-flow node that works with regular expressions immediately executing an expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexExecution` instead.
@@ -31,7 +31,7 @@ module RegexExecution {
}
/**
- * A data-flow node that works with regular expressions.
+ * A data-flow node that works with regular expressions immediately executing an expression.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexExecution::Range` instead.
@@ -46,17 +46,33 @@ class RegexExecution extends DataFlow::Node {
Attribute getRegexMethod() { result = range.getRegexMethod() }
}
-class RegexEscape extends DataFlow::CallCfgNode {
- DataFlow::Node regexNode;
- Attribute regexMethod;
+/** Provides classes for modeling Regular Expression escape-related APIs. */
+module RegexEscape {
+ /**
+ * A data-flow node that collects functions escaping regular expressions.
+ *
+ * Extend this class to model new APIs. If you want to refine existing API models,
+ * extend `RegexEscape` instead.
+ */
+ abstract class Range extends DataFlow::Node {
+ abstract DataFlow::Node getRegexNode();
- RegexEscape() {
- this = API::moduleImport("re").getMember("escape").getACall() and
- regexNode = this.getArg(0) and
- regexMethod = this.asExpr().(Attribute)
+ abstract Attribute getEscapeMethod();
}
-
- DataFlow::Node getRegexNode() { result = regexNode }
-
- Attribute getRegexMethod() { result = regexMethod }
+}
+
+/**
+ * A data-flow node that collects functions escaping regular expressions.
+ *
+ * Extend this class to refine existing API models. If you want to model new APIs,
+ * extend `RegexEscape::Range` instead.
+ */
+class RegexEscape extends DataFlow::Node {
+ RegexEscape::Range range;
+
+ RegexEscape() { this = range }
+
+ DataFlow::Node getRegexNode() { result = range.getRegexNode() }
+
+ Attribute getEscapeMethod() { result = range.getEscapeMethod() }
}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 5a3441bed83..0b5c57c1c67 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -53,4 +53,19 @@ private module Re {
override Attribute getRegexMethod() { result = regexMethod }
}
+
+ class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
+ DataFlow::Node regexNode;
+ Attribute escapeMethod;
+
+ ReEscape() {
+ this = API::moduleImport("re").getMember("escape").getACall() and
+ regexNode = this.getArg(0) and
+ escapeMethod = this.asExpr().(Attribute)
+ }
+
+ override DataFlow::Node getRegexNode() { result = regexNode }
+
+ override Attribute getEscapeMethod() { result = escapeMethod }
+ }
}
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index f82af085db0..fb2ef2ed192 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -21,6 +21,6 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
override predicate isSanitizer(DataFlow::Node sanitizer) {
- sanitizer = sanitizer.(RegexEscape).getRegexNode()
+ sanitizer = any(RegexEscape reEscape).getRegexNode()
}
}
From c127b109d0ccf29db088f2f2f0e4d58107444df1 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 16:21:34 +0100
Subject: [PATCH 049/168] Create re.compile().ReMethod test
---
.../Security/CWE-730/{ => unit_tests}/re_bad.py | 8 ++++++--
.../Security/CWE-730/{ => unit_tests}/re_good.py | 9 +++++++--
2 files changed, 13 insertions(+), 4 deletions(-)
rename python/ql/src/experimental/Security/CWE-730/{ => unit_tests}/re_bad.py (72%)
rename python/ql/src/experimental/Security/CWE-730/{ => unit_tests}/re_good.py (71%)
diff --git a/python/ql/src/experimental/Security/CWE-730/re_bad.py b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
similarity index 72%
rename from python/ql/src/experimental/Security/CWE-730/re_bad.py
rename to python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
index 6a0aa7c6614..172fb94bab8 100644
--- a/python/ql/src/experimental/Security/CWE-730/re_bad.py
+++ b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
@@ -1,3 +1,5 @@
+# move outside test folder
+
from flask import request, Flask
import re
@@ -7,16 +9,18 @@ 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("")
+@app.route("/compile_direct")
+def compile_direct():
+ re.compile(request.args['pattern']).search("")
+
# if __name__ == "__main__":
# app.run(debug=True)
diff --git a/python/ql/src/experimental/Security/CWE-730/re_good.py b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
similarity index 71%
rename from python/ql/src/experimental/Security/CWE-730/re_good.py
rename to python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
index ba09b1fe30b..a226d7a8899 100644
--- a/python/ql/src/experimental/Security/CWE-730/re_good.py
+++ b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
@@ -1,3 +1,5 @@
+# move outside test folder
+
from flask import request, Flask
import re
@@ -7,16 +9,19 @@ 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("")
+@app.route("/compile_direct")
+def compile_direct():
+ re.compile(re.escape(request.args['pattern'])).search("")
+
+
# if __name__ == "__main__":
# app.run(debug=True)
From 35f1c45d3234ddd679d852f8266d62b9449486bf Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 17:01:53 +0100
Subject: [PATCH 050/168] Change from Attribute to DataFlow::CallCfgNode in
getRegexMethod()
---
.../src/experimental/semmle/python/Concepts.qll | 8 ++++----
.../semmle/python/frameworks/Stdlib.qll | 16 ++++++++--------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index b4723c9e99d..8530047e60c 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -26,7 +26,7 @@ module RegexExecution {
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
- abstract Attribute getRegexMethod();
+ abstract DataFlow::CallCfgNode getRegexMethod();
}
}
@@ -43,7 +43,7 @@ class RegexExecution extends DataFlow::Node {
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
- Attribute getRegexMethod() { result = range.getRegexMethod() }
+ DataFlow::CallCfgNode getRegexMethod() { result = range.getRegexMethod() }
}
/** Provides classes for modeling Regular Expression escape-related APIs. */
@@ -57,7 +57,7 @@ module RegexEscape {
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
- abstract Attribute getEscapeMethod();
+ abstract DataFlow::CallCfgNode getEscapeMethod();
}
}
@@ -74,5 +74,5 @@ class RegexEscape extends DataFlow::Node {
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
- Attribute getEscapeMethod() { result = range.getEscapeMethod() }
+ DataFlow::CallCfgNode getEscapeMethod() { result = range.getEscapeMethod() }
}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 0b5c57c1c67..635c7a5803f 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -21,22 +21,22 @@ private module Re {
private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
- Attribute regexMethod;
+ DataFlow::CallCfgNode regexMethod;
DirectRegex() {
this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
regexNode = this.getArg(0) and
- regexMethod = this.asExpr().(Attribute)
+ regexMethod = this
}
override DataFlow::Node getRegexNode() { result = regexNode }
- override Attribute getRegexMethod() { result = regexMethod }
+ override DataFlow::CallCfgNode getRegexMethod() { result = regexMethod }
}
private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
- Attribute regexMethod;
+ DataFlow::CallCfgNode regexMethod;
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DirectRegex reMethod |
@@ -51,21 +51,21 @@ private module Re {
override DataFlow::Node getRegexNode() { result = regexNode }
- override Attribute getRegexMethod() { result = regexMethod }
+ override DataFlow::CallCfgNode getRegexMethod() { result = regexMethod }
}
class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
DataFlow::Node regexNode;
- Attribute escapeMethod;
+ DataFlow::CallCfgNode escapeMethod;
ReEscape() {
this = API::moduleImport("re").getMember("escape").getACall() and
regexNode = this.getArg(0) and
- escapeMethod = this.asExpr().(Attribute)
+ escapeMethod = this
}
override DataFlow::Node getRegexNode() { result = regexNode }
- override Attribute getEscapeMethod() { result = escapeMethod }
+ override DataFlow::CallCfgNode getEscapeMethod() { result = escapeMethod }
}
}
From 36cc7b5e3fee327db28144f142ac94268611a0c6 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 17:19:01 +0100
Subject: [PATCH 051/168] Fix CompiledRegex
---
.../experimental/semmle/python/frameworks/Stdlib.qll | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 635c7a5803f..44305b0bc03 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -31,6 +31,7 @@ private module Re {
override DataFlow::Node getRegexNode() { result = regexNode }
+ // pending obj.this discussion
override DataFlow::CallCfgNode getRegexMethod() { result = regexMethod }
}
@@ -39,13 +40,13 @@ private module Re {
DataFlow::CallCfgNode regexMethod;
CompiledRegex() {
- exists(DataFlow::CallCfgNode patternCall, DirectRegex reMethod |
- this = reMethod and
+ exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.(DataFlow::AttrRead).getObject().getALocalSource() and
+ patternCall = reMethod.getObject().getALocalSource() and
+ reMethod.getAttributeName() instanceof ReMethods and
regexNode = patternCall.getArg(0) and
- // regexMethod is *not* worked out outside class instanciation because `CompiledRegex` focuses on re.compile(pattern).ReMethod
- regexMethod = reMethod.getRegexMethod()
+ regexMethod = this
)
}
From 53d61c4fb68445ea88e8b8753aaf65341771dc78 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Fri, 26 Mar 2021 19:18:14 +0100
Subject: [PATCH 052/168] Use custom Sink
---
.../Security/CWE-730/RegexInjection.ql | 14 ++++++++++----
.../ql/src/experimental/semmle/python/Concepts.qll | 13 +++++++++++++
.../semmle/python/frameworks/Stdlib.qll | 2 ++
.../python/security/injection/RegexInjection.qll | 3 +--
4 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index 9d3da12f9bd..ab6d11de53c 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -16,7 +16,13 @@ import python
import experimental.semmle.python.security.injection.RegexInjection
import DataFlow::PathGraph
-from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "$@ regular expression is constructed from a $@.",
- sink.getNode(), "This", source.getNode(), "user-provided value"
+from
+ RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
+ Attribute sinkAttribute
+where
+ config.hasFlowPath(source, sink) and
+ sinkAttribute = sink.getNode().(RegexInjectionSink).getRegexMethod()
+select sink.getNode(), source, sink,
+ "$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
+ source.getNode(), "user-provided value", sinkAttribute,
+ sinkAttribute.getObject().toString() + "." + sinkAttribute.getName()
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 8530047e60c..ab30e97f8d9 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -76,3 +76,16 @@ class RegexEscape extends DataFlow::Node {
DataFlow::CallCfgNode getEscapeMethod() { result = range.getEscapeMethod() }
}
+
+class RegexInjectionSink extends DataFlow::Node {
+ Attribute regexMethod;
+
+ RegexInjectionSink() {
+ exists(RegexExecution reExec |
+ this = reExec.getRegexNode() and
+ regexMethod = reExec.getRegexMethod().getFunction().asExpr().(Attribute)
+ )
+ }
+
+ Attribute getRegexMethod() { result = regexMethod }
+}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 44305b0bc03..5ba4a652244 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -24,6 +24,7 @@ private module Re {
DataFlow::CallCfgNode regexMethod;
DirectRegex() {
+ // this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
regexNode = this.getArg(0) and
regexMethod = this
@@ -41,6 +42,7 @@ private module Re {
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
+ // this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index fb2ef2ed192..c2112175bfa 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -8,7 +8,6 @@ import experimental.semmle.python.Concepts
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
-import semmle.python.ApiGraphs
/**
* A taint-tracking configuration for detecting regular expression injections.
@@ -18,7 +17,7 @@ class RegexInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
- override predicate isSink(DataFlow::Node sink) { sink = any(RegexExecution re).getRegexNode() }
+ override predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink }
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer = any(RegexEscape reEscape).getRegexNode()
From 18ce257fc8bea35cdbc97437fd04dd1da9957a1e Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 00:26:30 +0100
Subject: [PATCH 053/168] Move RegexInjectionSink to query config (qll)
---
.../ql/src/experimental/semmle/python/Concepts.qll | 13 -------------
.../python/security/injection/RegexInjection.qll | 13 +++++++++++++
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index ab30e97f8d9..8530047e60c 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -76,16 +76,3 @@ class RegexEscape extends DataFlow::Node {
DataFlow::CallCfgNode getEscapeMethod() { result = range.getEscapeMethod() }
}
-
-class RegexInjectionSink extends DataFlow::Node {
- Attribute regexMethod;
-
- RegexInjectionSink() {
- exists(RegexExecution reExec |
- this = reExec.getRegexNode() and
- regexMethod = reExec.getRegexMethod().getFunction().asExpr().(Attribute)
- )
- }
-
- Attribute getRegexMethod() { result = regexMethod }
-}
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index c2112175bfa..358d884687b 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -9,6 +9,19 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
+class RegexInjectionSink extends DataFlow::Node {
+ Attribute regexMethod;
+
+ RegexInjectionSink() {
+ exists(RegexExecution reExec |
+ this = reExec.getRegexNode() and
+ regexMethod = reExec.getRegexMethod().getFunction().asExpr().(Attribute)
+ )
+ }
+
+ Attribute getRegexMethod() { result = regexMethod }
+}
+
/**
* A taint-tracking configuration for detecting regular expression injections.
*/
From e78e2ac2667740a7899436ffeae8bf9e1b4e2dfa Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 00:36:00 +0100
Subject: [PATCH 054/168] Get rid of (get)regexMethod
---
.../src/experimental/semmle/python/Concepts.qll | 8 --------
.../semmle/python/frameworks/Stdlib.qll | 16 +++-------------
.../python/security/injection/RegexInjection.qll | 2 +-
3 files changed, 4 insertions(+), 22 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 8530047e60c..46bb8ad4ee3 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -25,8 +25,6 @@ module RegexExecution {
*/
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
-
- abstract DataFlow::CallCfgNode getRegexMethod();
}
}
@@ -42,8 +40,6 @@ class RegexExecution extends DataFlow::Node {
RegexExecution() { this = range }
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
-
- DataFlow::CallCfgNode getRegexMethod() { result = range.getRegexMethod() }
}
/** Provides classes for modeling Regular Expression escape-related APIs. */
@@ -56,8 +52,6 @@ module RegexEscape {
*/
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
-
- abstract DataFlow::CallCfgNode getEscapeMethod();
}
}
@@ -73,6 +67,4 @@ class RegexEscape extends DataFlow::Node {
RegexEscape() { this = range }
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
-
- DataFlow::CallCfgNode getEscapeMethod() { result = range.getEscapeMethod() }
}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 5ba4a652244..28f07eddff4 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -26,14 +26,10 @@ private module Re {
DirectRegex() {
// this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
- regexNode = this.getArg(0) and
- regexMethod = this
+ regexNode = this.getArg(0)
}
override DataFlow::Node getRegexNode() { result = regexNode }
-
- // pending obj.this discussion
- override DataFlow::CallCfgNode getRegexMethod() { result = regexMethod }
}
private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
@@ -47,14 +43,11 @@ private module Re {
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
reMethod.getAttributeName() instanceof ReMethods and
- regexNode = patternCall.getArg(0) and
- regexMethod = this
+ regexNode = patternCall.getArg(0)
)
}
override DataFlow::Node getRegexNode() { result = regexNode }
-
- override DataFlow::CallCfgNode getRegexMethod() { result = regexMethod }
}
class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
@@ -63,12 +56,9 @@ private module Re {
ReEscape() {
this = API::moduleImport("re").getMember("escape").getACall() and
- regexNode = this.getArg(0) and
- escapeMethod = this
+ regexNode = this.getArg(0)
}
override DataFlow::Node getRegexNode() { result = regexNode }
-
- override DataFlow::CallCfgNode getEscapeMethod() { result = escapeMethod }
}
}
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 358d884687b..b77eae22371 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -15,7 +15,7 @@ class RegexInjectionSink extends DataFlow::Node {
RegexInjectionSink() {
exists(RegexExecution reExec |
this = reExec.getRegexNode() and
- regexMethod = reExec.getRegexMethod().getFunction().asExpr().(Attribute)
+ regexMethod = reExec.asExpr().(Attribute)
)
}
From a5850f4a9908e99df007cabaeae2460d920b4772 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 11:32:58 +0100
Subject: [PATCH 055/168] Use getRegexModule to know used lib
---
.../src/experimental/Security/CWE-730/RegexInjection.ql | 8 ++++----
python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++++
.../src/experimental/semmle/python/frameworks/Stdlib.qll | 7 ++++---
.../semmle/python/security/injection/RegexInjection.qll | 6 +++---
4 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index ab6d11de53c..422c57c9bff 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -18,11 +18,11 @@ import DataFlow::PathGraph
from
RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
- Attribute sinkAttribute
+ RegexInjectionSink castedSink
where
config.hasFlowPath(source, sink) and
- sinkAttribute = sink.getNode().(RegexInjectionSink).getRegexMethod()
+ castedSink = sink.getNode()
select sink.getNode(), source, sink,
"$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
- source.getNode(), "user-provided value", sinkAttribute,
- sinkAttribute.getObject().toString() + "." + sinkAttribute.getName()
+ source.getNode(), "user-provided value", castedSink,
+ castedSink.getRegexModule() + "." + castedSink.asExpr().(Attribute).getName()
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 46bb8ad4ee3..6bdf1a37bb0 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -25,6 +25,8 @@ module RegexExecution {
*/
abstract class Range extends DataFlow::Node {
abstract DataFlow::Node getRegexNode();
+
+ abstract string getRegexModule();
}
}
@@ -40,6 +42,8 @@ class RegexExecution extends DataFlow::Node {
RegexExecution() { this = range }
DataFlow::Node getRegexNode() { result = range.getRegexNode() }
+
+ string getRegexModule() { result = range.getRegexModule() }
}
/** Provides classes for modeling Regular Expression escape-related APIs. */
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 28f07eddff4..a4a860711b8 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -21,15 +21,15 @@ private module Re {
private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
- DataFlow::CallCfgNode regexMethod;
DirectRegex() {
- // this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
regexNode = this.getArg(0)
}
override DataFlow::Node getRegexNode() { result = regexNode }
+
+ override string getRegexModule() { result = "re" }
}
private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
@@ -38,7 +38,6 @@ private module Re {
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
- // this.getLocation().getFile().getBaseName().regexpMatch("^re_(good|bad)\\.py$") and // debug
this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
@@ -48,6 +47,8 @@ private module Re {
}
override DataFlow::Node getRegexNode() { result = regexNode }
+
+ override string getRegexModule() { result = "re" }
}
class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index b77eae22371..c4e06abf390 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -10,16 +10,16 @@ import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
class RegexInjectionSink extends DataFlow::Node {
- Attribute regexMethod;
+ string regexModule;
RegexInjectionSink() {
exists(RegexExecution reExec |
this = reExec.getRegexNode() and
- regexMethod = reExec.asExpr().(Attribute)
+ regexModule = reExec.getRegexModule()
)
}
- Attribute getRegexMethod() { result = regexMethod }
+ string getRegexModule() { result = regexModule }
}
/**
From f75110365fdc9cef4c18ba4a5395f1f8699bd54b Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 19:54:30 +0100
Subject: [PATCH 056/168] Fix Sink utilization in select
---
.../experimental/Security/CWE-730/RegexInjection.ql | 13 +++++--------
.../python/security/injection/RegexInjection.qll | 6 +++++-
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index 422c57c9bff..73178ca1c03 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -16,13 +16,10 @@ import python
import experimental.semmle.python.security.injection.RegexInjection
import DataFlow::PathGraph
-from
- RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
- RegexInjectionSink castedSink
-where
- config.hasFlowPath(source, sink) and
- castedSink = sink.getNode()
+from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
+where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
- source.getNode(), "user-provided value", castedSink,
- castedSink.getRegexModule() + "." + castedSink.asExpr().(Attribute).getName()
+ source.getNode(), "user-provided value", sink.getNode(),
+ sink.getNode().(RegexInjectionSink).getRegexModule() + "." +
+ sink.getNode().(RegexInjectionSink).getRegexMethod().getName()
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index c4e06abf390..2f0fa71ef79 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -11,15 +11,19 @@ import semmle.python.dataflow.new.RemoteFlowSources
class RegexInjectionSink extends DataFlow::Node {
string regexModule;
+ Attribute regexMethod;
RegexInjectionSink() {
exists(RegexExecution reExec |
this = reExec.getRegexNode() and
- regexModule = reExec.getRegexModule()
+ regexModule = reExec.getRegexModule() and
+ regexMethod = reExec.(DataFlow::CallCfgNode).getFunction().asExpr().(Attribute)
)
}
string getRegexModule() { result = regexModule }
+
+ Attribute getRegexMethod() { result = regexMethod }
}
/**
From 66ee67a7817037495f28909d2c6b75be4006a7e7 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 19:59:39 +0100
Subject: [PATCH 057/168] Polished select statement
---
.../Security/CWE-730/RegexInjection.ql | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index 73178ca1c03..77355fdf30d 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -16,10 +16,14 @@ import python
import experimental.semmle.python.security.injection.RegexInjection
import DataFlow::PathGraph
-from RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
-where config.hasFlowPath(source, sink)
+from
+ RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
+ RegexInjectionSink castedSink, Attribute methodAttribute
+where
+ config.hasFlowPath(source, sink) and
+ castedSink = sink.getNode() and
+ methodAttribute = castedSink.getRegexMethod()
select sink.getNode(), source, sink,
"$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
- source.getNode(), "user-provided value", sink.getNode(),
- sink.getNode().(RegexInjectionSink).getRegexModule() + "." +
- sink.getNode().(RegexInjectionSink).getRegexMethod().getName()
+ source.getNode(), "user-provided value", methodAttribute,
+ castedSink.getRegexModule() + "." + methodAttribute.getName()
From c54f08f33a00571ac2b1454c87b2cefbfd3e8b4d Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 20:13:32 +0100
Subject: [PATCH 058/168] Improve qhelp
---
.../Security/CWE-730/RegexInjection.qhelp | 65 ++++++++++++++-----
1 file changed, 47 insertions(+), 18 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
index 2e3d238daa4..0fc0445e07b 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
@@ -1,23 +1,52 @@
-
+
-
-
-
If a regular expression is built by a not escaped user-provided value, a user is likely to be able to cause a Denial of Service.
-
+
+
+ Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
+ be able to modify the meaning of the expression. In particular, such a user may be able to provide
+ a regular expression fragment that takes exponential time in the worst case, and use that to
+ perform a Denial of Service attack.
+
+
-
-
In case user input must compose a regular expression, it should be escaped with functions such as re.escape.
-
+
+
+ Before embedding user input into a regular expression, use a sanitization function such as
+ re.escape to escape meta-characters that have a special meaning regarding
+ regular expressions' syntax.
+
+ The following examples are based on a simple Flask web server environment.
+
+
+ The following example shows a HTTP request parameter that is used to construct a regular expression
+ without sanitizing it first:
+
+
+
+ Instead, the request parameter should be sanitized first, for example using the function
+ re.escape. This ensures that the user cannot insert characters which have a
+ special meaning in regular expressions.
+
\ No newline at end of file
From 0e169ba10ebfbc1c0fe56fc347d3abb857577b9f Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 20:14:11 +0100
Subject: [PATCH 059/168] Format qhelp
---
.../Security/CWE-730/RegexInjection.qhelp | 96 +++++++++----------
1 file changed, 48 insertions(+), 48 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
index 0fc0445e07b..3e635017da1 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
@@ -1,52 +1,52 @@
-
+
+
+
+
+ Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
+ be able to modify the meaning of the expression. In particular, such a user may be able to provide
+ a regular expression fragment that takes exponential time in the worst case, and use that to
+ perform a Denial of Service attack.
+
+
-
-
- Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
- be able to modify the meaning of the expression. In particular, such a user may be able to provide
- a regular expression fragment that takes exponential time in the worst case, and use that to
- perform a Denial of Service attack.
-
-
+
+
+ Before embedding user input into a regular expression, use a sanitization function such as
+ re.escape to escape meta-characters that have a special meaning regarding
+ regular expressions' syntax.
+
+
-
-
- Before embedding user input into a regular expression, use a sanitization function such as
- re.escape to escape meta-characters that have a special meaning regarding
- regular expressions' syntax.
-
-
+
+
+ The following examples are based on a simple Flask web server environment.
+
+
+ The following example shows a HTTP request parameter that is used to construct a regular expression
+ without sanitizing it first:
+
+
+
+ Instead, the request parameter should be sanitized first, for example using the function
+ re.escape. This ensures that the user cannot insert characters which have a
+ special meaning in regular expressions.
+
+
+
-
-
- The following examples are based on a simple Flask web server environment.
-
-
- The following example shows a HTTP request parameter that is used to construct a regular expression
- without sanitizing it first:
-
-
-
- Instead, the request parameter should be sanitized first, for example using the function
- re.escape. This ensures that the user cannot insert characters which have a
- special meaning in regular expressions.
-
+
\ No newline at end of file
From d49c23fe67035e676148ee9b690b00e2e894ada0 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 20:26:55 +0100
Subject: [PATCH 060/168] Improve tests' readability
---
.../Security/CWE-730/unit_tests/re_bad.py | 30 +++++++++++++----
.../Security/CWE-730/unit_tests/re_good.py | 32 +++++++++++++++----
2 files changed, 48 insertions(+), 14 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
index 172fb94bab8..55b306c8857 100644
--- a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
+++ b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
@@ -1,5 +1,3 @@
-# move outside test folder
-
from flask import request, Flask
import re
@@ -8,19 +6,37 @@ app = Flask(__name__)
@app.route("/direct")
def direct():
- pattern = request.args['pattern']
- re.search(pattern, "")
+ """
+ A RemoteFlowSource is used directly as re.search's pattern
+ """
+ unsafe_pattern = request.args["pattern"]
+ re.search(unsafe_pattern, "")
+
+
+# A RemoteFlowSource is used directly as re.compile's pattern
@app.route("/compile")
def compile():
- pattern = re.compile(request.args['pattern'])
- pattern.search("")
+ """
+ A RemoteFlowSource is used directly as re.compile's pattern
+ which also executes .search()
+ """
+
+ unsafe_pattern = request.args["pattern"]
+ compiled_pattern = re.compile(unsafe_pattern)
+ compiled_pattern.search("")
@app.route("/compile_direct")
def compile_direct():
- re.compile(request.args['pattern']).search("")
+ """
+ A RemoteFlowSource is used directly as re.compile's pattern
+ which also executes .search() in the same line
+ """
+
+ unsafe_pattern = request.args["pattern"]
+ re.compile(unsafe_pattern).search("")
# if __name__ == "__main__":
# app.run(debug=True)
diff --git a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
index a226d7a8899..6dc58b87f85 100644
--- a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
+++ b/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
@@ -1,5 +1,3 @@
-# move outside test folder
-
from flask import request, Flask
import re
@@ -8,19 +6,39 @@ app = Flask(__name__)
@app.route("/direct")
def direct():
- pattern = re.escape(request.args['pattern'])
- re.search(pattern, "")
+ """
+ A RemoteFlowSource is escaped by re.escape and then used as
+ re'search pattern
+ """
+
+ unsafe_pattern = request.args['pattern']
+ safe_pattern = re.escape(unsafe_pattern)
+ re.search(safe_pattern, "")
@app.route("/compile")
def compile():
- pattern = re.compile(re.escape(request.args['pattern']))
- pattern.search("")
+ """
+ A RemoteFlowSource is escaped by re.escape and used as re.compile's
+ pattern which also executes .search()
+ """
+
+ unsafe_pattern = request.args['pattern']
+ safe_pattern = re.escape(unsafe_pattern)
+ compiled_pattern = re.compile(safe_pattern)
+ compiled_pattern.search("")
@app.route("/compile_direct")
def compile_direct():
- re.compile(re.escape(request.args['pattern'])).search("")
+ """
+ A RemoteFlowSource is escaped by re.escape and then used as re.compile's
+ pattern which also executes .search() in the same line
+ """
+
+ unsafe_pattern = request.args['pattern']
+ safe_pattern = re.escape(unsafe_pattern)
+ re.compile(safe_pattern).search("")
# if __name__ == "__main__":
From d4a89b2fd822689f626523d0da786f077ca7464f Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 20:29:11 +0100
Subject: [PATCH 061/168] Fix qhelp typo while converting to python's regex
injection
---
.../ql/src/experimental/Security/CWE-730/RegexInjection.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
index 3e635017da1..3c1d5907a77 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
@@ -31,7 +31,7 @@
re.escape. This ensures that the user cannot insert characters which have a
special meaning in regular expressions.
-
+
From b6721971dd9149992fd53524a99f878c7220fcc2 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 20:54:46 +0100
Subject: [PATCH 062/168] Improve code comments
---
.../experimental/semmle/python/Concepts.qll | 9 +++++
.../semmle/python/frameworks/Stdlib.qll | 38 ++++++++++++++++---
.../security/injection/RegexInjection.qll | 5 +++
3 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 6bdf1a37bb0..b325925f321 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -24,8 +24,14 @@ module RegexExecution {
* extend `RegexExecution` instead.
*/
abstract class Range extends DataFlow::Node {
+ /**
+ * Gets the argument containing the executed expression.
+ */
abstract DataFlow::Node getRegexNode();
+ /**
+ * Gets the library used to execute the regular expression.
+ */
abstract string getRegexModule();
}
}
@@ -55,6 +61,9 @@ module RegexEscape {
* extend `RegexEscape` instead.
*/
abstract class Range extends DataFlow::Node {
+ /**
+ * Gets the argument containing the escaped expression.
+ */
abstract DataFlow::Node getRegexNode();
}
}
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index a4a860711b8..c825bcfc086 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -10,20 +10,33 @@ private import semmle.python.dataflow.new.RemoteFlowSources
private import experimental.semmle.python.Concepts
private import semmle.python.ApiGraphs
-/** Provides models for the Python standard library. */
+/**
+ * Provides models for Python's `re` library.
+ *
+ * See https://docs.python.org/3/library/re.html
+ */
private module Re {
- /** List of re methods. */
- private class ReMethods extends string {
- ReMethods() {
+ /**
+ * List of `re` methods immediately executing an expression.
+ *
+ * See https://docs.python.org/3/library/re.html#module-contents
+ */
+ private class RegexExecutionMethods extends string {
+ RegexExecutionMethods() {
this in ["match", "fullmatch", "search", "split", "findall", "finditer", "sub", "subn"]
}
}
+ /**
+ * A class to find `re` methods immediately executing an expression.
+ *
+ * See `RegexExecutionMethods`
+ */
private class DirectRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
DirectRegex() {
- this = API::moduleImport("re").getMember(any(ReMethods m)).getACall() and
+ this = API::moduleImport("re").getMember(any(RegexExecutionMethods m)).getACall() and
regexNode = this.getArg(0)
}
@@ -32,6 +45,14 @@ private module Re {
override string getRegexModule() { result = "re" }
}
+ /**
+ * A class to find `re` methods immediately executing an expression from a
+ * compiled expression by `re.compile`.
+ *
+ * See `RegexExecutionMethods`
+ *
+ * See https://docs.python.org/3/library/re.html#regular-expression-objects
+ */
private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
DataFlow::CallCfgNode regexMethod;
@@ -41,7 +62,7 @@ private module Re {
this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
patternCall = reMethod.getObject().getALocalSource() and
- reMethod.getAttributeName() instanceof ReMethods and
+ reMethod.getAttributeName() instanceof RegexExecutionMethods and
regexNode = patternCall.getArg(0)
)
}
@@ -51,6 +72,11 @@ private module Re {
override string getRegexModule() { result = "re" }
}
+ /**
+ * A class to find `re` methods escaping an expression.
+ *
+ * See https://docs.python.org/3/library/re.html#re.escape
+ */
class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
DataFlow::Node regexNode;
DataFlow::CallCfgNode escapeMethod;
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 2f0fa71ef79..2ce6f06edc0 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -9,6 +9,11 @@ import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources
+/**
+ * A class to find methods executing regular expressions.
+ *
+ * See `RegexExecution`
+ */
class RegexInjectionSink extends DataFlow::Node {
string regexModule;
Attribute regexMethod;
From 36555149245fc55d0fd72dc1953342956a386c71 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 21:01:07 +0100
Subject: [PATCH 063/168] Fix ambiguity
---
python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index c825bcfc086..849dd47467d 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -46,8 +46,7 @@ private module Re {
}
/**
- * A class to find `re` methods immediately executing an expression from a
- * compiled expression by `re.compile`.
+ * A class to find `re` methods immediately executing a compiled expression by `re.compile`.
*
* See `RegexExecutionMethods`
*
From fc27c6c5470043c4c6b5cf96d2abded89ef152e6 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 21:03:19 +0100
Subject: [PATCH 064/168] Fix RegexExecution ambiguity
---
python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index b325925f321..08131064912 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -18,7 +18,7 @@ private import semmle.python.ApiGraphs
/** Provides classes for modeling Regular Expression-related APIs. */
module RegexExecution {
/**
- * A data-flow node that works with regular expressions immediately executing an expression.
+ * A data-flow node that collects methods immediately executing an expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexExecution` instead.
@@ -37,7 +37,7 @@ module RegexExecution {
}
/**
- * A data-flow node that works with regular expressions immediately executing an expression.
+ * A data-flow node that collect methods immediately executing an expression.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexExecution::Range` instead.
From 03825a6052a1d9412e02aaca7990f094e596f9a3 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 21:05:49 +0100
Subject: [PATCH 065/168] Add comment to Sink's predicates
---
.../semmle/python/security/injection/RegexInjection.qll | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index 2ce6f06edc0..a7a0526f750 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -26,8 +26,14 @@ class RegexInjectionSink extends DataFlow::Node {
)
}
+ /**
+ * Gets the argument containing the executed expression.
+ */
string getRegexModule() { result = regexModule }
+ /**
+ * Gets the mthod used to execute the regular expression.
+ */
Attribute getRegexMethod() { result = regexMethod }
}
From ec85ee453777eed7053859692a257cb89da5400f Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sat, 27 Mar 2021 21:07:53 +0100
Subject: [PATCH 066/168] Sink's predicate typo
---
.../semmle/python/security/injection/RegexInjection.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
index a7a0526f750..7b7b08cacab 100644
--- a/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
+++ b/python/ql/src/experimental/semmle/python/security/injection/RegexInjection.qll
@@ -32,7 +32,7 @@ class RegexInjectionSink extends DataFlow::Node {
string getRegexModule() { result = regexModule }
/**
- * Gets the mthod used to execute the regular expression.
+ * Gets the method used to execute the regular expression.
*/
Attribute getRegexMethod() { result = regexMethod }
}
From d401d18e7193558eedd1c17c82b6f46ef504d39f Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sun, 28 Mar 2021 01:22:12 +0100
Subject: [PATCH 067/168] Add .expected and qlref
---
.../Security/CWE-730/RegexInjection.expected | 27 +++++++++++++++++++
.../Security/CWE-730/RegexInjection.qlref | 1 +
2 files changed, 28 insertions(+)
create mode 100644 python/ql/src/experimental/Security/CWE-730/RegexInjection.expected
create mode 100644 python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.expected b/python/ql/src/experimental/Security/CWE-730/RegexInjection.expected
new file mode 100644
index 00000000000..9886df2904d
--- /dev/null
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.expected
@@ -0,0 +1,27 @@
+edges
+| re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute |
+| re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript |
+| re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern |
+| re_bad.py:26:22:26:28 | ControlFlowNode for request | re_bad.py:26:22:26:33 | ControlFlowNode for Attribute |
+| re_bad.py:26:22:26:33 | ControlFlowNode for Attribute | re_bad.py:26:22:26:44 | ControlFlowNode for Subscript |
+| re_bad.py:26:22:26:44 | ControlFlowNode for Subscript | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern |
+| re_bad.py:38:22:38:28 | ControlFlowNode for request | re_bad.py:38:22:38:33 | ControlFlowNode for Attribute |
+| re_bad.py:38:22:38:33 | ControlFlowNode for Attribute | re_bad.py:38:22:38:44 | ControlFlowNode for Subscript |
+| re_bad.py:38:22:38:44 | ControlFlowNode for Subscript | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern |
+nodes
+| re_bad.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
+| re_bad.py:26:22:26:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| re_bad.py:26:22:26:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| re_bad.py:26:22:26:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
+| re_bad.py:38:22:38:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| re_bad.py:38:22:38:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| re_bad.py:38:22:38:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
+#select
+| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:13 | Attribute | re.search |
+| re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | re_bad.py:26:22:26:28 | ControlFlowNode for request | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | This | re_bad.py:26:22:26:28 | ControlFlowNode for request | user-provided value | re_bad.py:28:5:28:27 | Attribute | re.search |
+| re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | re_bad.py:38:22:38:28 | ControlFlowNode for request | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | This | re_bad.py:38:22:38:28 | ControlFlowNode for request | user-provided value | re_bad.py:39:5:39:37 | Attribute | re.search |
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref
new file mode 100644
index 00000000000..c0c506c4707
--- /dev/null
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE-730/RegexInjection.ql
From 81d23c066c4fbad99914aa3410e57e328c5c2375 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sun, 28 Mar 2021 01:37:55 +0100
Subject: [PATCH 068/168] Move tests and qlref from /src to /test
---
.../query-tests}/Security/CWE-730/RegexInjection.qlref | 0
.../experimental/query-tests/Security/CWE-730}/re_bad.py | 0
.../experimental/query-tests/Security/CWE-730}/re_good.py | 0
3 files changed, 0 insertions(+), 0 deletions(-)
rename python/ql/{src/experimental => test/experimental/query-tests}/Security/CWE-730/RegexInjection.qlref (100%)
rename python/ql/{src/experimental/Security/CWE-730/unit_tests => test/experimental/query-tests/Security/CWE-730}/re_bad.py (100%)
rename python/ql/{src/experimental/Security/CWE-730/unit_tests => test/experimental/query-tests/Security/CWE-730}/re_good.py (100%)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/RegexInjection.qlref
rename to python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.qlref
diff --git a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/unit_tests/re_bad.py
rename to python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py
diff --git a/python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py b/python/ql/test/experimental/query-tests/Security/CWE-730/re_good.py
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/unit_tests/re_good.py
rename to python/ql/test/experimental/query-tests/Security/CWE-730/re_good.py
From d968eea9143fda8d6118d1cf906f0a23fd673065 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Sun, 28 Mar 2021 18:36:59 +0200
Subject: [PATCH 069/168] Move expected to /test
---
.../query-tests}/Security/CWE-730/RegexInjection.expected | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename python/ql/{src/experimental => test/experimental/query-tests}/Security/CWE-730/RegexInjection.expected (100%)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected
similarity index 100%
rename from python/ql/src/experimental/Security/CWE-730/RegexInjection.expected
rename to python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected
From 6a20a4dcc32f9dc0016e39446c579de4e5389b0e Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Mon, 29 Mar 2021 15:01:58 +0200
Subject: [PATCH 070/168] Add newline to qhelp
---
.../ql/src/experimental/Security/CWE-730/RegexInjection.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
index 3c1d5907a77..94e66b2b89c 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
@@ -49,4 +49,4 @@
SonarSource: RSPEC-2631
-
\ No newline at end of file
+
From 3fae3fd93e25a7913d762a00d0869a4c3cfabd13 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Tue, 30 Mar 2021 17:39:27 +0200
Subject: [PATCH 071/168] Take ApiGraphs out of Concepts.qll
---
python/ql/src/experimental/semmle/python/Concepts.qll | 1 -
1 file changed, 1 deletion(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 08131064912..07bbae2a060 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -13,7 +13,6 @@ private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.RemoteFlowSources
private import semmle.python.dataflow.new.TaintTracking
private import experimental.semmle.python.Frameworks
-private import semmle.python.ApiGraphs
/** Provides classes for modeling Regular Expression-related APIs. */
module RegexExecution {
From 05ee853c4e380f5580b17620fce1e4aa4ca14ab6 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Tue, 6 Apr 2021 15:52:31 +0200
Subject: [PATCH 072/168] Remove wrong comment
---
.../ql/test/experimental/query-tests/Security/CWE-730/re_bad.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py
index 55b306c8857..622eaf199f6 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py
+++ b/python/ql/test/experimental/query-tests/Security/CWE-730/re_bad.py
@@ -14,8 +14,6 @@ def direct():
re.search(unsafe_pattern, "")
-# A RemoteFlowSource is used directly as re.compile's pattern
-
@app.route("/compile")
def compile():
"""
From 12ccd7e3b643899b1abff49056390e6adb40a763 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 8 Apr 2021 22:20:09 +0200
Subject: [PATCH 073/168] Update .expected
---
.../Security/CWE-730/RegexInjection.expected | 32 +++++++++----------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected
index 9886df2904d..97ed0d1bdfa 100644
--- a/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected
+++ b/python/ql/test/experimental/query-tests/Security/CWE-730/RegexInjection.expected
@@ -2,26 +2,26 @@ edges
| re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute |
| re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript |
| re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern |
-| re_bad.py:26:22:26:28 | ControlFlowNode for request | re_bad.py:26:22:26:33 | ControlFlowNode for Attribute |
-| re_bad.py:26:22:26:33 | ControlFlowNode for Attribute | re_bad.py:26:22:26:44 | ControlFlowNode for Subscript |
-| re_bad.py:26:22:26:44 | ControlFlowNode for Subscript | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern |
-| re_bad.py:38:22:38:28 | ControlFlowNode for request | re_bad.py:38:22:38:33 | ControlFlowNode for Attribute |
-| re_bad.py:38:22:38:33 | ControlFlowNode for Attribute | re_bad.py:38:22:38:44 | ControlFlowNode for Subscript |
-| re_bad.py:38:22:38:44 | ControlFlowNode for Subscript | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern |
+| re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:24:22:24:33 | ControlFlowNode for Attribute |
+| re_bad.py:24:22:24:33 | ControlFlowNode for Attribute | re_bad.py:24:22:24:44 | ControlFlowNode for Subscript |
+| re_bad.py:24:22:24:44 | ControlFlowNode for Subscript | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern |
+| re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:36:22:36:33 | ControlFlowNode for Attribute |
+| re_bad.py:36:22:36:33 | ControlFlowNode for Attribute | re_bad.py:36:22:36:44 | ControlFlowNode for Subscript |
+| re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern |
nodes
| re_bad.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
| re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
-| re_bad.py:26:22:26:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| re_bad.py:26:22:26:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
-| re_bad.py:26:22:26:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
-| re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
-| re_bad.py:38:22:38:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
-| re_bad.py:38:22:38:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
-| re_bad.py:38:22:38:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
-| re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
+| re_bad.py:24:22:24:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| re_bad.py:24:22:24:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| re_bad.py:24:22:24:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
+| re_bad.py:36:22:36:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request |
+| re_bad.py:36:22:36:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
+| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern |
#select
| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:13 | Attribute | re.search |
-| re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | re_bad.py:26:22:26:28 | ControlFlowNode for request | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:27:35:27:48 | ControlFlowNode for unsafe_pattern | This | re_bad.py:26:22:26:28 | ControlFlowNode for request | user-provided value | re_bad.py:28:5:28:27 | Attribute | re.search |
-| re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | re_bad.py:38:22:38:28 | ControlFlowNode for request | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:39:16:39:29 | ControlFlowNode for unsafe_pattern | This | re_bad.py:38:22:38:28 | ControlFlowNode for request | user-provided value | re_bad.py:39:5:39:37 | Attribute | re.search |
+| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:27 | Attribute | re.search |
+| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | $@ regular expression is constructed from a $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:37 | Attribute | re.search |
From c4322848ec8525dc70ed5c7ee7d6381362621aeb Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 8 Apr 2021 22:42:35 +0200
Subject: [PATCH 074/168] Polish qhelp
---
.../Security/CWE-730/RegexInjection.qhelp | 87 +++++++++----------
.../experimental/Security/CWE-730/re_bad.py | 15 ++++
.../experimental/Security/CWE-730/re_good.py | 17 ++++
3 files changed, 72 insertions(+), 47 deletions(-)
create mode 100644 python/ql/src/experimental/Security/CWE-730/re_bad.py
create mode 100644 python/ql/src/experimental/Security/CWE-730/re_good.py
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
index 94e66b2b89c..f19f0744469 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.qhelp
@@ -1,52 +1,45 @@
-
+
-
-
- Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
- be able to modify the meaning of the expression. In particular, such a user may be able to provide
- a regular expression fragment that takes exponential time in the worst case, and use that to
- perform a Denial of Service attack.
-
-
+
+
+Constructing a regular expression with unsanitized user input is dangerous as a malicious user may
+be able to modify the meaning of the expression. In particular, such a user may be able to provide
+a regular expression fragment that takes exponential time in the worst case, and use that to
+perform a Denial of Service attack.
+
+
-
-
- Before embedding user input into a regular expression, use a sanitization function such as
- re.escape to escape meta-characters that have a special meaning regarding
- regular expressions' syntax.
-
-
+
+
+Before embedding user input into a regular expression, use a sanitization function such as
+re.escape to escape meta-characters that have a special meaning regarding
+regular expressions' syntax.
+
+
-
-
- The following examples are based on a simple Flask web server environment.
-
-
- The following example shows a HTTP request parameter that is used to construct a regular expression
- without sanitizing it first:
-
-
-
- Instead, the request parameter should be sanitized first, for example using the function
- re.escape. This ensures that the user cannot insert characters which have a
- special meaning in regular expressions.
-
-
-
+
+
+The following examples are based on a simple Flask web server environment.
+
+
+The following example shows a HTTP request parameter that is used to construct a regular expression
+without sanitizing it first:
+
+
+
+Instead, the request parameter should be sanitized first, for example using the function
+re.escape. This ensures that the user cannot insert characters which have a
+special meaning in regular expressions.
+
+
diff --git a/python/ql/src/experimental/Security/CWE-730/re_bad.py b/python/ql/src/experimental/Security/CWE-730/re_bad.py
new file mode 100644
index 00000000000..3befaba9a01
--- /dev/null
+++ b/python/ql/src/experimental/Security/CWE-730/re_bad.py
@@ -0,0 +1,15 @@
+from flask import request, Flask
+import re
+
+
+@app.route("/direct")
+def direct():
+ unsafe_pattern = request.args["pattern"]
+ re.search(unsafe_pattern, "")
+
+
+@app.route("/compile")
+def compile():
+ unsafe_pattern = request.args["pattern"]
+ compiled_pattern = re.compile(unsafe_pattern)
+ compiled_pattern.search("")
diff --git a/python/ql/src/experimental/Security/CWE-730/re_good.py b/python/ql/src/experimental/Security/CWE-730/re_good.py
new file mode 100644
index 00000000000..cdc9a7ac158
--- /dev/null
+++ b/python/ql/src/experimental/Security/CWE-730/re_good.py
@@ -0,0 +1,17 @@
+from flask import request, Flask
+import re
+
+
+@app.route("/direct")
+def direct():
+ unsafe_pattern = request.args['pattern']
+ safe_pattern = re.escape(unsafe_pattern)
+ re.search(safe_pattern, "")
+
+
+@app.route("/compile")
+def compile():
+ unsafe_pattern = request.args['pattern']
+ safe_pattern = re.escape(unsafe_pattern)
+ compiled_pattern = re.compile(safe_pattern)
+ compiled_pattern.search("")
From c0c71c509c4f9bbf31b665763ed89deeebae90c3 Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Tue, 27 Apr 2021 19:21:43 +0200
Subject: [PATCH 075/168] Apply suggestions from code review
Update `RegexExecution` docs and use `flowsTo()` instead of `getALocalSource()`.
Co-authored-by: yoff
---
python/ql/src/experimental/semmle/python/Concepts.qll | 2 +-
python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index 07bbae2a060..e11e21da914 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -17,7 +17,7 @@ private import experimental.semmle.python.Frameworks
/** Provides classes for modeling Regular Expression-related APIs. */
module RegexExecution {
/**
- * A data-flow node that collects methods immediately executing an expression.
+ * A data-flow node that executes a regular expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexExecution` instead.
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 849dd47467d..1e3478c55f5 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -60,7 +60,7 @@ private module Re {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
this.getFunction() = reMethod and
patternCall = API::moduleImport("re").getMember("compile").getACall() and
- patternCall = reMethod.getObject().getALocalSource() and
+ patternCall.flowsTo(reMethod.getObject()) and
reMethod.getAttributeName() instanceof RegexExecutionMethods and
regexNode = patternCall.getArg(0)
)
From 20b532ec5e3b57790cf20ea7ebc587b9fcadc10d Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Tue, 27 Apr 2021 19:24:25 +0200
Subject: [PATCH 076/168] Update to-cast sink's naming
Signed-off-by: jorgectf
---
.../src/experimental/Security/CWE-730/RegexInjection.ql | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
index 77355fdf30d..7725f636eb0 100644
--- a/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
+++ b/python/ql/src/experimental/Security/CWE-730/RegexInjection.ql
@@ -18,12 +18,12 @@ import DataFlow::PathGraph
from
RegexInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
- RegexInjectionSink castedSink, Attribute methodAttribute
+ RegexInjectionSink regexInjectionSink, Attribute methodAttribute
where
config.hasFlowPath(source, sink) and
- castedSink = sink.getNode() and
- methodAttribute = castedSink.getRegexMethod()
+ regexInjectionSink = sink.getNode() and
+ methodAttribute = regexInjectionSink.getRegexMethod()
select sink.getNode(), source, sink,
"$@ regular expression is constructed from a $@ and executed by $@.", sink.getNode(), "This",
source.getNode(), "user-provided value", methodAttribute,
- castedSink.getRegexModule() + "." + methodAttribute.getName()
+ regexInjectionSink.getRegexModule() + "." + methodAttribute.getName()
From 8a800986a290a89492df3d6161d4547d80015bf4 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Tue, 27 Apr 2021 19:26:04 +0200
Subject: [PATCH 077/168] Remove unused class variables
Signed-off-by: jorgectf
---
python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 --
1 file changed, 2 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 1e3478c55f5..c7a8842cad7 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -54,7 +54,6 @@ private module Re {
*/
private class CompiledRegex extends DataFlow::CallCfgNode, RegexExecution::Range {
DataFlow::Node regexNode;
- DataFlow::CallCfgNode regexMethod;
CompiledRegex() {
exists(DataFlow::CallCfgNode patternCall, DataFlow::AttrRead reMethod |
@@ -78,7 +77,6 @@ private module Re {
*/
class ReEscape extends DataFlow::CallCfgNode, RegexEscape::Range {
DataFlow::Node regexNode;
- DataFlow::CallCfgNode escapeMethod;
ReEscape() {
this = API::moduleImport("re").getMember("escape").getACall() and
From 21e01b809fe169f281dbc539e1cc6460dd22edf3 Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Tue, 27 Apr 2021 19:52:26 +0200
Subject: [PATCH 078/168] Add code example in CompiledRegex
Signed-off-by: jorgectf
---
.../experimental/semmle/python/frameworks/Stdlib.qll | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index c7a8842cad7..9bda2cb3158 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -48,6 +48,17 @@ private module Re {
/**
* A class to find `re` methods immediately executing a compiled expression by `re.compile`.
*
+ * Given the following example:
+ *
+ * ```py
+ * pattern = re.compile(input)
+ * input.match(s)
+ * ```
+ *
+ * `patternCall` refers to `re.compile(input)`,
+ * `regexNode` refers to `input` and
+ * `this` will refer to `input.match(s)`
+ *
* See `RegexExecutionMethods`
*
* See https://docs.python.org/3/library/re.html#regular-expression-objects
From e8347c2c20e6b8c4c150e443372159bcb3034abf Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 27 Apr 2021 10:43:45 +0200
Subject: [PATCH 079/168] C++: Update data-flow caching
---
.../cpp/dataflow/internal/DataFlowUtil.qll | 1 -
.../dataflow/internal/TaintTrackingUtil.qll | 1 +
.../cpp/ir/dataflow/DefaultTaintTracking.qll | 233 ++++++++++--------
.../ir/dataflow/internal/DataFlowDispatch.qll | 4 +-
.../cpp/ir/dataflow/internal/DataFlowUtil.qll | 21 +-
5 files changed, 143 insertions(+), 117 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll
index 690f24fc59a..75e8c8922d0 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll
@@ -526,7 +526,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
* This is the local flow predicate that's used as a building block in global
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
-cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Expr -> Expr
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll
index 591f461c8eb..6216045db32 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll
@@ -45,6 +45,7 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
* different objects.
*/
+cached
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// Taint can flow through expressions that alter the value but preserve
// more than one bit of it _or_ expressions that follow data through
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll
index 3092031cbc7..49d11a7e3cc 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll
@@ -165,105 +165,132 @@ private predicate nodeIsBarrierEqualityCandidate(
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
-private predicate nodeIsBarrier(DataFlow::Node node) {
- exists(Variable checkedVar |
- readsVariable(node.asInstruction(), checkedVar) and
- hasUpperBoundsCheck(checkedVar)
- )
- or
- exists(Variable checkedVar, Operand access |
- /*
- * This node is guarded by a condition that forces the accessed variable
- * to equal something else. For example:
- * ```
- * x = taintsource()
- * if (x == 10) {
- * taintsink(x); // not considered tainted
- * }
- * ```
- */
-
- nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
- readsVariable(access.getDef(), checkedVar)
- )
-}
-
-private predicate nodeIsBarrierIn(DataFlow::Node node) {
- // don't use dataflow into taint sources, as this leads to duplicate results.
- exists(Expr source | isUserInput(source, _) |
- node = DataFlow::exprNode(source)
+cached
+private module Cached {
+ cached
+ predicate nodeIsBarrier(DataFlow::Node node) {
+ exists(Variable checkedVar |
+ readsVariable(node.asInstruction(), checkedVar) and
+ hasUpperBoundsCheck(checkedVar)
+ )
or
- // This case goes together with the similar (but not identical) rule in
- // `getNodeForSource`.
- node = DataFlow::definitionByReferenceNodeFromArgument(source)
- )
- or
- // don't use dataflow into binary instructions if both operands are unpredictable
- exists(BinaryInstruction iTo |
- iTo = node.asInstruction() and
- not predictableInstruction(iTo.getLeft()) and
- not predictableInstruction(iTo.getRight()) and
- // propagate taint from either the pointer or the offset, regardless of predictability
- not iTo instanceof PointerArithmeticInstruction
- )
- or
- // don't use dataflow through calls to pure functions if two or more operands
- // are unpredictable
- exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
- iTo = node.asInstruction() and
- isPureFunction(iTo.getStaticCallTarget().getName()) and
- iFrom1 = iTo.getAnArgument() and
- iFrom2 = iTo.getAnArgument() and
- not predictableInstruction(iFrom1) and
- not predictableInstruction(iFrom2) and
- iFrom1 != iFrom2
- )
+ exists(Variable checkedVar, Operand access |
+ /*
+ * This node is guarded by a condition that forces the accessed variable
+ * to equal something else. For example:
+ * ```
+ * x = taintsource()
+ * if (x == 10) {
+ * taintsink(x); // not considered tainted
+ * }
+ * ```
+ */
+
+ nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
+ readsVariable(access.getDef(), checkedVar)
+ )
+ }
+
+ cached
+ predicate nodeIsBarrierIn(DataFlow::Node node) {
+ // don't use dataflow into taint sources, as this leads to duplicate results.
+ exists(Expr source | isUserInput(source, _) |
+ node = DataFlow::exprNode(source)
+ or
+ // This case goes together with the similar (but not identical) rule in
+ // `getNodeForSource`.
+ node = DataFlow::definitionByReferenceNodeFromArgument(source)
+ )
+ or
+ // don't use dataflow into binary instructions if both operands are unpredictable
+ exists(BinaryInstruction iTo |
+ iTo = node.asInstruction() and
+ not predictableInstruction(iTo.getLeft()) and
+ not predictableInstruction(iTo.getRight()) and
+ // propagate taint from either the pointer or the offset, regardless of predictability
+ not iTo instanceof PointerArithmeticInstruction
+ )
+ or
+ // don't use dataflow through calls to pure functions if two or more operands
+ // are unpredictable
+ exists(Instruction iFrom1, Instruction iFrom2, CallInstruction iTo |
+ iTo = node.asInstruction() and
+ isPureFunction(iTo.getStaticCallTarget().getName()) and
+ iFrom1 = iTo.getAnArgument() and
+ iFrom2 = iTo.getAnArgument() and
+ not predictableInstruction(iFrom1) and
+ not predictableInstruction(iFrom2) and
+ iFrom1 != iFrom2
+ )
+ }
+
+ cached
+ Element adjustedSink(DataFlow::Node sink) {
+ // TODO: is it more appropriate to use asConvertedExpr here and avoid
+ // `getConversion*`? Or will that cause us to miss some cases where there's
+ // flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
+ // pretend there was flow to the converted `Expr` for the sake of
+ // compatibility.
+ sink.asExpr().getConversion*() = result
+ or
+ // For compatibility, send flow from arguments to parameters, even for
+ // functions with no body.
+ exists(FunctionCall call, int i |
+ sink.asExpr() = call.getArgument(i) and
+ result = resolveCall(call).getParameter(i)
+ )
+ or
+ // For compatibility, send flow into a `Variable` if there is flow to any
+ // Load or Store of that variable.
+ exists(CopyInstruction copy |
+ copy.getSourceValue() = sink.asInstruction() and
+ (
+ readsVariable(copy, result) or
+ writesVariable(copy, result)
+ ) and
+ not hasUpperBoundsCheck(result)
+ )
+ or
+ // For compatibility, send flow into a `NotExpr` even if it's part of a
+ // short-circuiting condition and thus might get skipped.
+ result.(NotExpr).getOperand() = sink.asExpr()
+ or
+ // Taint postfix and prefix crement operations when their operand is tainted.
+ result.(CrementOperation).getAnOperand() = sink.asExpr()
+ or
+ // Taint `e1 += e2`, `e &= e2` and friends when `e1` or `e2` is tainted.
+ result.(AssignOperation).getAnOperand() = sink.asExpr()
+ or
+ result =
+ sink.asOperand()
+ .(SideEffectOperand)
+ .getUse()
+ .(ReadSideEffectInstruction)
+ .getArgumentDef()
+ .getUnconvertedResultExpression()
+ }
+
+ /**
+ * Step to return value of a modeled function when an input taints the
+ * dereference of the return value.
+ */
+ cached
+ predicate additionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
+ exists(CallInstruction call, Function func, FunctionInput modelIn, FunctionOutput modelOut |
+ n1.asOperand() = callInput(call, modelIn) and
+ (
+ func.(TaintFunction).hasTaintFlow(modelIn, modelOut)
+ or
+ func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
+ ) and
+ call.getStaticCallTarget() = func and
+ modelOut.isReturnValueDeref() and
+ call = n2.asInstruction()
+ )
+ }
}
-private Element adjustedSink(DataFlow::Node sink) {
- // TODO: is it more appropriate to use asConvertedExpr here and avoid
- // `getConversion*`? Or will that cause us to miss some cases where there's
- // flow to a conversion (like a `ReferenceDereferenceExpr`) and we want to
- // pretend there was flow to the converted `Expr` for the sake of
- // compatibility.
- sink.asExpr().getConversion*() = result
- or
- // For compatibility, send flow from arguments to parameters, even for
- // functions with no body.
- exists(FunctionCall call, int i |
- sink.asExpr() = call.getArgument(i) and
- result = resolveCall(call).getParameter(i)
- )
- or
- // For compatibility, send flow into a `Variable` if there is flow to any
- // Load or Store of that variable.
- exists(CopyInstruction copy |
- copy.getSourceValue() = sink.asInstruction() and
- (
- readsVariable(copy, result) or
- writesVariable(copy, result)
- ) and
- not hasUpperBoundsCheck(result)
- )
- or
- // For compatibility, send flow into a `NotExpr` even if it's part of a
- // short-circuiting condition and thus might get skipped.
- result.(NotExpr).getOperand() = sink.asExpr()
- or
- // Taint postfix and prefix crement operations when their operand is tainted.
- result.(CrementOperation).getAnOperand() = sink.asExpr()
- or
- // Taint `e1 += e2`, `e &= e2` and friends when `e1` or `e2` is tainted.
- result.(AssignOperation).getAnOperand() = sink.asExpr()
- or
- result =
- sink.asOperand()
- .(SideEffectOperand)
- .getUse()
- .(ReadSideEffectInstruction)
- .getArgumentDef()
- .getUnconvertedResultExpression()
-}
+private import Cached
/**
* Holds if `tainted` may contain taint from `source`.
@@ -402,19 +429,7 @@ module TaintedWithPath {
readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable))
)
or
- // Step to return value of a modeled function when an input taints the
- // dereference of the return value
- exists(CallInstruction call, Function func, FunctionInput modelIn, FunctionOutput modelOut |
- n1.asOperand() = callInput(call, modelIn) and
- (
- func.(TaintFunction).hasTaintFlow(modelIn, modelOut)
- or
- func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)
- ) and
- call.getStaticCallTarget() = func and
- modelOut.isReturnValueDeref() and
- call = n2.asInstruction()
- )
+ additionalTaintStep(n1, n2)
}
override predicate isSanitizer(DataFlow::Node node) {
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll
index e927634fec2..99d8555f8ca 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll
@@ -2,11 +2,14 @@ private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
+private import DataFlowImplCommon as DataFlowImplCommon
/**
* Gets a function that might be called by `call`.
*/
+cached
Function viableCallable(CallInstruction call) {
+ DataFlowImplCommon::forceCachingInSameStage() and
result = call.getStaticCallTarget()
or
// If the target of the call does not have a body in the snapshot, it might
@@ -43,7 +46,6 @@ private module VirtualDispatch {
abstract DataFlow::Node getDispatchValue();
/** Gets a candidate target for this call. */
- cached
abstract Function resolve();
/**
diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
index f5fb7309cff..8ed61da4c92 100644
--- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
+++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
@@ -12,10 +12,20 @@ private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.models.interfaces.DataFlow
cached
-private newtype TIRDataFlowNode =
- TInstructionNode(Instruction i) or
- TOperandNode(Operand op) or
- TVariableNode(Variable var)
+private module Cached {
+ cached
+ newtype TIRDataFlowNode =
+ TInstructionNode(Instruction i) or
+ TOperandNode(Operand op) or
+ TVariableNode(Variable var)
+
+ cached
+ predicate localFlowStepCached(Node nodeFrom, Node nodeTo) {
+ simpleLocalFlowStep(nodeFrom, nodeTo)
+ }
+}
+
+private import Cached
/**
* A node in a data flow graph.
@@ -590,7 +600,7 @@ Node uninitializedNode(LocalVariable v) { none() }
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
*/
-predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
+predicate localFlowStep = localFlowStepCached/2;
/**
* INTERNAL: do not use.
@@ -598,7 +608,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
* This is the local flow predicate that's used as a building block in global
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
-cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Operand -> Instruction flow
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
From c35a2b959af56993a7cc659d09323a3328b62959 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 27 Apr 2021 11:37:17 +0200
Subject: [PATCH 080/168] Python: Update data-flow caching
---
.../dataflow/new/internal/DataFlowPrivate.qll | 2 -
.../new/internal/TaintTrackingPrivate.qll | 62 ++++++++++---------
2 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
index 9b0a8267270..a6640f41dc0 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
@@ -228,7 +228,6 @@ module EssaFlow {
* data flow. It is a strict subset of the `localFlowStep` predicate, as it
* excludes SSA flow through instance fields.
*/
-cached
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// If there is ESSA-flow out of a node `node`, we want flow
// both out of `node` and any post-update node of `node`.
@@ -1559,7 +1558,6 @@ predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node no
* any value stored inside `f` is cleared at the pre-update node associated with `x`
* in `x.f = newValue`.
*/
-cached
predicate clearsContent(Node n, Content c) {
exists(CallNode call, CallableValue callable, string name |
call_unpacks(call, _, callable, name, _) and
diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll b/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
index f12d97d2fa5..a6e169243db 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
@@ -9,36 +9,42 @@ private import semmle.python.dataflow.new.internal.TaintTrackingPublic
*/
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
-/**
- * Holds if the additional step from `nodeFrom` to `nodeTo` should be included in all
- * global taint flow configurations.
- */
-predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
- localAdditionalTaintStep(nodeFrom, nodeTo)
- or
- any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
+private module Cached {
+ /**
+ * Holds if the additional step from `nodeFrom` to `nodeTo` should be included in all
+ * global taint flow configurations.
+ */
+ cached
+ predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ localAdditionalTaintStep(nodeFrom, nodeTo)
+ or
+ any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
+ }
+
+ /**
+ * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
+ * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
+ * different objects.
+ */
+ cached
+ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
+ concatStep(nodeFrom, nodeTo)
+ or
+ subscriptStep(nodeFrom, nodeTo)
+ or
+ stringManipulation(nodeFrom, nodeTo)
+ or
+ containerStep(nodeFrom, nodeTo)
+ or
+ copyStep(nodeFrom, nodeTo)
+ or
+ forStep(nodeFrom, nodeTo)
+ or
+ unpackingAssignmentStep(nodeFrom, nodeTo)
+ }
}
-/**
- * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
- * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
- * different objects.
- */
-predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
- concatStep(nodeFrom, nodeTo)
- or
- subscriptStep(nodeFrom, nodeTo)
- or
- stringManipulation(nodeFrom, nodeTo)
- or
- containerStep(nodeFrom, nodeTo)
- or
- copyStep(nodeFrom, nodeTo)
- or
- forStep(nodeFrom, nodeTo)
- or
- unpackingAssignmentStep(nodeFrom, nodeTo)
-}
+import Cached
/**
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to concatenation.
From 213d011a8cfcd3179c7db3922fbe259ddc48df0d Mon Sep 17 00:00:00 2001
From: jorgectf
Date: Thu, 29 Apr 2021 11:10:03 +0200
Subject: [PATCH 081/168] Edit code example in CompiledRegex
Signed-off-by: jorgectf
---
.../src/experimental/semmle/python/frameworks/Stdlib.qll | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 9bda2cb3158..05ea4f62630 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -52,12 +52,13 @@ private module Re {
*
* ```py
* pattern = re.compile(input)
- * input.match(s)
+ * pattern.match(s)
* ```
*
- * `patternCall` refers to `re.compile(input)`,
- * `regexNode` refers to `input` and
- * `this` will refer to `input.match(s)`
+ * This class will identify that `re.compile` compiles `input` and afterwards
+ * executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)`
+ * and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument)
+ *
*
* See `RegexExecutionMethods`
*
From bd4b1893733ccdff3bc4ef564d03a15400e9b00b Mon Sep 17 00:00:00 2001
From: Jorge <46056498+jorgectf@users.noreply.github.com>
Date: Thu, 29 Apr 2021 16:26:28 +0200
Subject: [PATCH 082/168] Polish documentation consistency
Co-authored-by: yoff
---
python/ql/src/experimental/semmle/python/Concepts.qll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll
index e11e21da914..0661ebc5890 100644
--- a/python/ql/src/experimental/semmle/python/Concepts.qll
+++ b/python/ql/src/experimental/semmle/python/Concepts.qll
@@ -36,7 +36,7 @@ module RegexExecution {
}
/**
- * A data-flow node that collect methods immediately executing an expression.
+ * A data-flow node that executes a regular expression.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexExecution::Range` instead.
@@ -54,7 +54,7 @@ class RegexExecution extends DataFlow::Node {
/** Provides classes for modeling Regular Expression escape-related APIs. */
module RegexEscape {
/**
- * A data-flow node that collects functions escaping regular expressions.
+ * A data-flow node that escapes a regular expression.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `RegexEscape` instead.
@@ -68,7 +68,7 @@ module RegexEscape {
}
/**
- * A data-flow node that collects functions escaping regular expressions.
+ * A data-flow node that escapes a regular expression.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `RegexEscape::Range` instead.
From 8c3980d80b88e56db5c01265a9b2ca2c86bff197 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 2 May 2021 22:54:43 +0300
Subject: [PATCH 083/168] Update
cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
---
.../CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
index b09971b5328..53a50841977 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.c
@@ -3,7 +3,7 @@ while(intIndex > 2)
...
intIndex--;
...
-} // GOOD: coreten cycle
+} // GOOD: correct cycle
...
while(intIndex > 2)
{
From 0935c5a0f2a2fa2404eac279823ca2faecf6ab30 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 2 May 2021 22:58:30 +0300
Subject: [PATCH 084/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.ql
---
.../CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
index a253a5e0599..9acc1d35d81 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
@@ -26,7 +26,7 @@ class DangerousWhileLoop extends WhileStmt {
exp = this.getCondition().getAChild*() and
not exp instanceof PointerFieldAccess and
not exp instanceof ValueFieldAccess and
- exp.toString() = dl.getName() and
+ exp.(VariableAccess).getTarget().getName() = dl.getName() and
not exp.getParent*() instanceof CrementOperation and
not exp.getParent*() instanceof Assignment and
not exp.getParent*() instanceof FunctionCall
From 21f43252e6d48cc3638690225e762fc092c75f99 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 2 May 2021 22:59:04 +0300
Subject: [PATCH 085/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.expected
---
.../DeclarationOfVariableWithUnnecessarilyWideScope.expected | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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
index 7b540a33384..4b29dad8779 100644
--- 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
@@ -1 +1 @@
-| test.c:12:9:12:16 | intIndex | A variable with this name is used in the loop condition. |
+| test.c:13:9:13:16 | intIndex | A variable with this name is used in the loop condition. |
From bb97507ebc195ecdb43126c4fcab6741b274791e Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Sun, 2 May 2021 22:59:56 +0300
Subject: [PATCH 086/168] Update test.c
---
.../Security/CWE/CWE-1126/semmle/tests/test.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
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
index 090bed34d45..325c278f697 100644
--- 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
@@ -6,10 +6,27 @@ void workFunction_0(char *s) {
buf[intIndex] = 1;
intIndex--;
}
+ intIndex = 10;
while(intIndex > 2)
{
buf[intIndex] = 1;
int intIndex; // BAD
intIndex--;
}
+ intIndex = 10;
+ while(intIndex > 2) // GOOD
+ {
+ buf[intIndex] = 1;
+ intIndex -= 2;
+ int intIndex;
+ intIndex--;
+ }
+ intIndex = 10;
+ while(intIndex > 2) // GOOD
+ {
+ buf[intIndex] = 1;
+ --intIndex;
+ int intIndex;
+ intIndex--;
+ }
}
From 4709e8139d88ff445352716fdc6177e8a4995d70 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Mon, 3 May 2021 01:43:56 +0000
Subject: [PATCH 087/168] JPython code injection
---
.../CWE/CWE-094/JPythonInjection.java | 48 ++++
.../CWE/CWE-094/JPythonInjection.qhelp | 34 +++
.../Security/CWE/CWE-094/JPythonInjection.ql | 68 +++++
.../CWE-094/JPythonInjection.expected | 11 +
.../security/CWE-094/JPythonInjection.java | 64 +++++
.../security/CWE-094/JPythonInjection.qlref | 1 +
.../query-tests/security/CWE-094/options | 2 +-
.../jpython-2.7.2/org/python/core/PyCode.java | 43 +++
.../org/python/core/PyException.java | 12 +
.../org/python/core/PyObject.java | 11 +
.../org/python/core/PySystemState.java | 177 ++++++++++++
.../org/python/core/ThreadState.java | 28 ++
.../org/python/util/PythonInterpreter.java | 252 ++++++++++++++++++
13 files changed, 750 insertions(+), 1 deletion(-)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.ql
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java
create mode 100644 java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
new file mode 100644
index 00000000000..13db6830a71
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
@@ -0,0 +1,48 @@
+public class JPythonInjection extends HttpServlet {
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new PythonInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+
+ // BAD: allow arbitrary JPython expression to execute
+ interpreter.exec(code);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ out.close();
+ }
+ }
+
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+
+ try {
+ interpreter = new PythonInterpreter();
+ // BAD: allow arbitrary JPython expression to evaluate
+ PyObject py = interpreter.eval(code);
+
+ response.getWriter().print(py.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+}
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
new file mode 100644
index 00000000000..dddbb2d618a
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
@@ -0,0 +1,34 @@
+
+
+
+
+
Python has been the most widely used programming language in recent years, and JPython
+ is a popular Java implementation of Python. It allows embedded Python scripting inside
+ Java applications and provides an interactive interpreter that can be used to interact
+ with Java packages or with running Java applications. If an expression is built using
+ attacker-controlled data and then evaluated, it may allow the attacker to run arbitrary
+ code.
+
+
+
+
In general, including user input in JPython expression should be avoided. If user input
+ must be included in an expression, it should be then evaluated in a safe context that
+ doesn't allow arbitrary code invocation.
+
+
+
+
The following code could execute random code in JPython Interpreter
+
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.ql
new file mode 100644
index 00000000000..a6621d89c26
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.ql
@@ -0,0 +1,68 @@
+/**
+ * @name Injection in JPython
+ * @description Evaluation of a user-controlled malicious expression in JPython
+ * may lead to remote code execution.
+ * @kind path-problem
+ * @id java/jpython-injection
+ * @tags security
+ * external/cwe/cwe-094
+ * external/cwe/cwe-095
+ */
+
+import java
+import semmle.code.java.dataflow.FlowSources
+import DataFlow::PathGraph
+
+/** The class `org.python.util.PythonInterpreter`. */
+class PythonInterpreter extends RefType {
+ PythonInterpreter() { this.hasQualifiedName("org.python.util", "PythonInterpreter") }
+}
+
+/** A method that evaluates, compiles or executes a JPython expression. */
+class InterpretExprMethod extends Method {
+ InterpretExprMethod() {
+ this.getDeclaringType().getAnAncestor*() instanceof PythonInterpreter and
+ (
+ hasName("exec") or
+ hasName("eval") or
+ hasName("compile")
+ )
+ }
+}
+
+/** Holds if a JPython expression if evaluated, compiled or executed. */
+predicate runCode(MethodAccess ma, Expr sink) {
+ exists(Method m | m = ma.getMethod() |
+ m instanceof InterpretExprMethod and
+ sink = ma.getArgument(0)
+ )
+}
+
+/** Sink of an expression interpreted by JPython interpreter. */
+class CodeInjectionSink extends DataFlow::ExprNode {
+ CodeInjectionSink() { runCode(_, this.getExpr()) }
+
+ MethodAccess getMethodAccess() { runCode(result, this.getExpr()) }
+}
+
+class CodeInjectionConfiguration extends TaintTracking::Configuration {
+ CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
+
+ override predicate isSource(DataFlow::Node source) {
+ source instanceof RemoteFlowSource
+ or
+ source instanceof LocalUserInput
+ }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
+
+ override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
+ // @RequestBody MyQueryObj query; interpreter.exec(query.getInterpreterCode());
+ exists(MethodAccess ma | ma.getQualifier() = node1.asExpr() and ma = node2.asExpr())
+ }
+}
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, CodeInjectionConfiguration conf
+where conf.hasFlowPath(source, sink)
+select sink.getNode().(CodeInjectionSink).getMethodAccess(), source, sink, "JPython evaluate $@.",
+ source.getNode(), "user input"
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
new file mode 100644
index 00000000000..f5816001939
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
@@ -0,0 +1,11 @@
+edges
+| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code |
+| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code |
+nodes
+| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JPythonInjection.java:30:28:30:31 | code | semmle.label | code |
+| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JPythonInjection.java:52:40:52:43 | code | semmle.label | code |
+#select
+| JPythonInjection.java:30:11:30:32 | exec(...) | JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code | JPython evaluate $@. | JPythonInjection.java:22:23:22:50 | getParameter(...) | user input |
+| JPythonInjection.java:52:23:52:44 | eval(...) | JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code | JPython evaluate $@. | JPythonInjection.java:47:21:47:48 | getParameter(...) | user input |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
new file mode 100644
index 00000000000..a0515eb4212
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
@@ -0,0 +1,64 @@
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.python.core.PyObject;
+import org.python.core.PyException;
+import org.python.util.PythonInterpreter;
+
+public class JPythonInjection extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public JPythonInjection() {
+ super();
+ }
+
+ // BAD: allow arbitrary JPython expression to execute
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new PythonInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+ interpreter.exec(code);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ out.close();
+ }
+ }
+
+ // BAD: allow arbitrary JPython expression to evaluate
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+
+ try {
+ interpreter = new PythonInterpreter();
+ PyObject py = interpreter.eval(code);
+
+ response.getWriter().print(py.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+}
+
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
new file mode 100644
index 00000000000..80217a193bd
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-094/JPythonInjection.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/options b/java/ql/test/experimental/query-tests/security/CWE-094/options
index 18e3518fc97..ccf3a24f215 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/options
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/options
@@ -1,2 +1,2 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jpython-2.7.2
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
new file mode 100644
index 00000000000..9b7c99f94fa
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
@@ -0,0 +1,43 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+/**
+ * A super class for all python code implementations.
+ */
+public abstract class PyCode extends PyObject
+{
+ abstract public PyObject call(ThreadState state,
+ PyObject args[], String keywords[],
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject self, PyObject args[],
+ String keywords[],
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject arg1, PyObject globals,
+ PyObject[] defaults, PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject arg1, PyObject arg2,
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject arg1, PyObject arg2, PyObject arg3,
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+ abstract public PyObject call(ThreadState state,
+ PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4,
+ PyObject globals, PyObject[] defaults,
+ PyObject closure);
+
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java
new file mode 100644
index 00000000000..3a0a6c52c69
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java
@@ -0,0 +1,12 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+import java.io.*;
+
+/**
+ * A wrapper for all python exception. Note that the well-known python exceptions are not
+ * subclasses of PyException. Instead the python exception class is stored in the type
+ * field and value or class instance is stored in the value field.
+ */
+public class PyException extends RuntimeException
+{
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java
new file mode 100644
index 00000000000..00993123461
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java
@@ -0,0 +1,11 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+import java.io.Serializable;
+
+/**
+ * All objects known to the Jython runtime system are represented by an instance of the class
+ * {@code PyObject} or one of its subclasses.
+ */
+public class PyObject implements Serializable {
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java
new file mode 100644
index 00000000000..8444bbba70e
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java
@@ -0,0 +1,177 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * The "sys" module.
+ */
+// xxx Many have lamented, this should really be a module!
+// but it will require some refactoring to see this wish come true.
+public class PySystemState extends PyObject {
+ public PySystemState() {
+ }
+
+ public static void classDictInit(PyObject dict) {
+ }
+
+ public ClassLoader getSyspathJavaLoader() {
+ return null;
+ }
+
+ // xxx fix this accessors
+ public PyObject __findattr_ex__(String name) {
+ return null;
+ }
+
+ public void __setattr__(String name, PyObject value) {
+ }
+
+ public void __delattr__(String name) {
+ }
+
+ public PyObject gettrace() {
+ return null;
+ }
+
+ public void settrace(PyObject tracefunc) {
+ }
+
+ /**
+ * Change the current working directory to the specified path.
+ *
+ * path is assumed to be absolute and canonical (via os.path.realpath).
+ *
+ * @param path a path String
+ */
+ public void setCurrentWorkingDir(String path) {
+ }
+
+ /**
+ * Return a string representing the current working directory.
+ *
+ * @return a path String
+ */
+ public String getCurrentWorkingDir() {
+ return null;
+ }
+
+ /**
+ * Resolve a path. Returns the full path taking the current working directory into account.
+ *
+ * @param path a path String
+ * @return a resolved path String
+ */
+ public String getPath(String path) {
+ return null;
+ }
+
+ /**
+ * Resolve a path, returning a {@link File}, taking the current working directory into account.
+ *
+ * @param path a path String
+ * @return a resolved File
+ */
+ public File getFile(String path) {
+ return null;
+ }
+
+ public ClassLoader getClassLoader() {
+ return null;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ }
+
+ public static Properties getBaseProperties() {
+ return null;
+ }
+
+ public static synchronized void initialize() {
+ }
+
+ public static synchronized void initialize(Properties preProperties,
+ Properties postProperties) {
+ }
+
+ public static synchronized void initialize(Properties preProperties, Properties postProperties,
+ String[] argv) {
+ }
+
+ public static synchronized void initialize(Properties preProperties, Properties postProperties,
+ String[] argv, ClassLoader classLoader) {
+ }
+
+ /**
+ * Add a classpath directory to the list of places that are searched for java packages.
+ *
+ * Note. Classes found in directory and sub-directory are not made available to jython by
+ * this call. It only makes the java package found in the directory available. This call is
+ * mostly useful if jython is embedded in an application that deals with its own class loaders.
+ * A servlet container is a very good example. Calling
+ * {@code add_classdir("/WEB-INF/classes")} makes the java packages in WEB-INF classes
+ * available to jython import. However the actual class loading is completely handled by the
+ * servlet container's context classloader.
+ */
+ public static void add_classdir(String directoryPath) {
+ }
+
+ /**
+ * Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip
+ * files. The .jar and .zip files found will not be cached.
+ *
+ * Note. Classes in .jar and .zip files found in the directory are not made available to
+ * jython by this call. See the note for add_classdir(dir) for more details.
+ *
+ * @param directoryPath The name of a directory.
+ *
+ * @see #add_classdir
+ */
+ public static void add_extdir(String directoryPath) {
+ }
+
+ /**
+ * Add a .jar and .zip directory to the list of places that are searched for java .jar and .zip
+ * files.
+ *
+ * Note. Classes in .jar and .zip files found in the directory are not made available to
+ * jython by this call. See the note for add_classdir(dir) for more details.
+ *
+ * @param directoryPath The name of a directory.
+ * @param cache Controls if the packages in the zip and jar file should be cached.
+ *
+ * @see #add_classdir
+ */
+ public static void add_extdir(String directoryPath, boolean cache) {
+ }
+
+ // Not public by design. We can't rebind the displayhook if
+ // a reflected function is inserted in the class dict.
+
+ /**
+ * Exit a Python program with the given status.
+ *
+ * @param status the value to exit with
+ * @throws PyException {@code SystemExit} always throws this exception. When caught at top level
+ * the program will exit.
+ */
+ public static void exit(PyObject status) {
+ }
+
+ /**
+ * Exit a Python program with the status 0.
+ */
+ public static void exit() {
+ }
+
+ public static void exc_clear() {
+ }
+
+ public void cleanup() {
+ }
+
+ public void close() {
+ }
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java b/java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java
new file mode 100644
index 00000000000..920270fe053
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java
@@ -0,0 +1,28 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+// a ThreadState refers to one PySystemState; this weak ref allows for tracking all ThreadState objects
+// that refer to a given PySystemState
+
+public class ThreadState {
+
+ public PyException exception;
+
+ public ThreadState(PySystemState systemState) {
+ setSystemState(systemState);
+ }
+
+ public void setSystemState(PySystemState systemState) {
+ }
+
+ public PySystemState getSystemState() {
+ return null;
+ }
+
+ public boolean enterRepr(PyObject obj) {
+ return false;
+ }
+
+ public void exitRepr(PyObject obj) {
+ }
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java b/java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java
new file mode 100644
index 00000000000..92c50917b59
--- /dev/null
+++ b/java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java
@@ -0,0 +1,252 @@
+package org.python.util;
+
+import java.io.Closeable;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Properties;
+
+import org.python.core.PyCode;
+import org.python.core.PyObject;
+
+/**
+ * The PythonInterpreter class is a standard wrapper for a Jython interpreter for embedding in a
+ * Java application.
+ */
+public class PythonInterpreter implements Closeable {
+
+ /**
+ * Initializes the Jython runtime. This should only be called once, before any other Python
+ * objects (including PythonInterpreter) are created.
+ *
+ * @param preProperties A set of properties. Typically System.getProperties() is used.
+ * preProperties override properties from the registry file.
+ * @param postProperties Another set of properties. Values like python.home, python.path and all
+ * other values from the registry files can be added to this property set.
+ * postProperties override system properties and registry properties.
+ * @param argv Command line arguments, assigned to sys.argv.
+ */
+ public static void
+ initialize(Properties preProperties, Properties postProperties, String[] argv) {
+ }
+
+ /**
+ * Creates a new interpreter with an empty local namespace.
+ */
+ public PythonInterpreter() {
+ }
+
+ /**
+ * Creates a new interpreter with the ability to maintain a separate local namespace for each
+ * thread (set by invoking setLocals()).
+ *
+ * @param dict a Python mapping object (e.g., a dictionary) for use as the default namespace
+ */
+ public static PythonInterpreter threadLocalStateInterpreter(PyObject dict) {
+ return null;
+ }
+
+ /**
+ * Creates a new interpreter with a specified local namespace.
+ *
+ * @param dict a Python mapping object (e.g., a dictionary) for use as the namespace
+ */
+ public PythonInterpreter(PyObject dict) {
+ }
+
+ /**
+ * Sets a Python object to use for the standard output stream, sys.stdout. This
+ * stream is used in a byte-oriented way (mostly) that depends on the type of file-like object.
+ * The behaviour as implemented is:
+ *
+ *
Stream behaviour for various object types
+ *
+ *
+ *
Python type of object o written
+ *
+ *
+ *
+ *
str/bytes
+ *
unicode
+ *
Any other type
+ *
+ *
+ *
{@link PyFile}
+ *
as bytes directly
+ *
respect {@link PyFile#encoding}
+ *
call str(o) first
+ *
+ *
+ *
{@link PyFileWriter}
+ *
each byte value as a char
+ *
write as Java chars
+ *
call o.toString() first
+ *
+ *
+ *
Other {@link PyObject} f
+ *
invoke f.write(str(o))
+ *
invoke f.write(o)
+ *
invoke f.write(str(o))
+ *
+ *
+ *
+ * @param outStream Python file-like object to use as the output stream
+ */
+ public void setOut(PyObject outStream) {
+ }
+
+ /**
+ * Sets a {@link java.io.Writer} to use for the standard output stream, sys.stdout.
+ * The behaviour as implemented is to output each object o by calling
+ * o.toString() and writing this as UTF-16.
+ *
+ * @param outStream to use as the output stream
+ */
+ public void setOut(java.io.Writer outStream) {
+ }
+
+ /**
+ * Sets a {@link java.io.OutputStream} to use for the standard output stream.
+ *
+ * @param outStream OutputStream to use as output stream
+ */
+ public void setOut(java.io.OutputStream outStream) {
+ }
+
+ /**
+ * Sets a Python object to use for the standard output stream, sys.stderr. This
+ * stream is used in a byte-oriented way (mostly) that depends on the type of file-like object,
+ * in the same way as {@link #setOut(PyObject)}.
+ *
+ * @param outStream Python file-like object to use as the error output stream
+ */
+ public void setErr(PyObject outStream) {
+ }
+
+ /**
+ * Sets a {@link java.io.Writer} to use for the standard output stream, sys.stdout.
+ * The behaviour as implemented is to output each object o by calling
+ * o.toString() and writing this as UTF-16.
+ *
+ * @param outStream to use as the error output stream
+ */
+ public void setErr(java.io.Writer outStream) {
+ }
+
+ public void setErr(java.io.OutputStream outStream) {
+ }
+
+ /**
+ * Evaluates a string as a Python expression and returns the result.
+ */
+ public PyObject eval(String s) {
+ return null;
+ }
+
+ /**
+ * Evaluates a Python code object and returns the result.
+ */
+ public PyObject eval(PyObject code) {
+ return null;
+ }
+
+ /**
+ * Executes a string of Python source in the local namespace.
+ *
+ * In some environments, such as Windows, Unicode characters in the script will be converted
+ * into ascii question marks (?). This can be avoided by first compiling the fragment using
+ * PythonInterpreter.compile(), and using the overridden form of this method which takes a
+ * PyCode object. Code page declarations are not supported.
+ */
+ public void exec(String s) {
+ }
+
+ /**
+ * Executes a Python code object in the local namespace.
+ */
+ public void exec(PyObject code) {
+ }
+
+ /**
+ * Executes a file of Python source in the local namespace.
+ */
+ public void execfile(String filename) {
+ }
+
+ public void execfile(java.io.InputStream s) {
+ }
+
+ public void execfile(java.io.InputStream s, String name) {
+ }
+
+ /**
+ * Compiles a string of Python source as either an expression (if possible) or a module.
+ *
+ * Designed for use by a JSR 223 implementation: "the Scripting API does not distinguish between
+ * scripts which return values and those which do not, nor do they make the corresponding
+ * distinction between evaluating or executing objects." (SCR.4.2.1)
+ */
+ public PyCode compile(String script) {
+ return null;
+ }
+
+ public PyCode compile(Reader reader) {
+ return null;
+ }
+
+ public PyCode compile(String script, String filename) {
+ return null;
+ }
+
+ public PyCode compile(Reader reader, String filename) {
+ return null;
+ }
+
+ /**
+ * Sets a variable in the local namespace.
+ *
+ * @param name the name of the variable
+ * @param value the object to set the variable to (as converted to an appropriate Python object)
+ */
+ public void set(String name, Object value) {
+ }
+
+ /**
+ * Sets a variable in the local namespace.
+ *
+ * @param name the name of the variable
+ * @param value the Python object to set the variable to
+ */
+ public void set(String name, PyObject value) {
+ }
+
+ /**
+ * Returns the value of a variable in the local namespace.
+ *
+ * @param name the name of the variable
+ * @return the value of the variable, or null if that name isn't assigned
+ */
+ public PyObject get(String name) {
+ return null;
+ }
+
+ /**
+ * Returns the value of a variable in the local namespace.
+ *
+ * The value will be returned as an instance of the given Java class.
+ * interp.get("foo", Object.class) will return the most appropriate generic Java
+ * object.
+ *
+ * @param name the name of the variable
+ * @param javaclass the class of object to return
+ * @return the value of the variable as the given class, or null if that name isn't assigned
+ */
+ public T get(String name, Class javaclass) {
+ return null;
+ }
+
+ public void cleanup() {
+ }
+
+ public void close() {
+ }
+}
From 703fbf139aaf828b1bd954f5b60714036a99df64 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 4 May 2021 02:54:49 +0000
Subject: [PATCH 088/168] Add more methods and update the library name
---
.../CWE/CWE-094/JPythonInjection.java | 48 ------
.../CWE/CWE-094/JPythonInjection.qhelp | 34 -----
.../Security/CWE/CWE-094/JPythonInjection.ql | 68 ---------
.../Security/CWE/CWE-094/JythonInjection.java | 47 ++++++
.../CWE/CWE-094/JythonInjection.qhelp | 34 +++++
.../Security/CWE/CWE-094/JythonInjection.ql | 123 +++++++++++++++
.../CWE-094/JPythonInjection.expected | 11 --
.../security/CWE-094/JPythonInjection.java | 64 --------
.../security/CWE-094/JPythonInjection.qlref | 1 -
.../security/CWE-094/JythonInjection.expected | 21 +++
.../security/CWE-094/JythonInjection.java | 144 ++++++++++++++++++
.../security/CWE-094/JythonInjection.qlref | 1 +
.../query-tests/security/CWE-094/options | 2 +-
.../org/python/antlr/base/mod.java | 5 +
.../org/python/core/BytecodeLoader.java | 47 ++++++
.../org/python/core/CompileMode.java | 11 ++
.../org/python/core/CompilerFlags.java | 17 +++
.../jython-2.7.2/org/python/core/Py.java | 134 ++++++++++++++++
.../org/python/core/PyCode.java | 0
.../org/python/core/PyException.java | 0
.../org/python/core/PyObject.java | 0
.../org/python/core/PySystemState.java | 0
.../org/python/core/ThreadState.java | 0
.../python/util/InteractiveInterpreter.java | 114 ++++++++++++++
.../org/python/util/PythonInterpreter.java | 0
25 files changed, 699 insertions(+), 227 deletions(-)
delete mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
delete mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
delete mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.ql
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.qlref
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/antlr/base/mod.java
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/core/BytecodeLoader.java
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/core/CompileMode.java
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/core/CompilerFlags.java
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/core/Py.java
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/core/PyCode.java (100%)
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/core/PyException.java (100%)
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/core/PyObject.java (100%)
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/core/PySystemState.java (100%)
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/core/ThreadState.java (100%)
create mode 100644 java/ql/test/stubs/jython-2.7.2/org/python/util/InteractiveInterpreter.java
rename java/ql/test/stubs/{jpython-2.7.2 => jython-2.7.2}/org/python/util/PythonInterpreter.java (100%)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
deleted file mode 100644
index 13db6830a71..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.java
+++ /dev/null
@@ -1,48 +0,0 @@
-public class JPythonInjection extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/plain");
- String code = request.getParameter("code");
- PythonInterpreter interpreter = null;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- try {
- interpreter = new PythonInterpreter();
- interpreter.setOut(out);
- interpreter.setErr(out);
-
- // BAD: allow arbitrary JPython expression to execute
- interpreter.exec(code);
- out.flush();
-
- response.getWriter().print(out.toString());
- } catch(PyException ex) {
- response.getWriter().println(ex.getMessage());
- } finally {
- if (interpreter != null) {
- interpreter.close();
- }
- out.close();
- }
- }
-
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/plain");
- String code = request.getParameter("code");
- PythonInterpreter interpreter = null;
-
- try {
- interpreter = new PythonInterpreter();
- // BAD: allow arbitrary JPython expression to evaluate
- PyObject py = interpreter.eval(code);
-
- response.getWriter().print(py.toString());
- } catch(PyException ex) {
- response.getWriter().println(ex.getMessage());
- } finally {
- if (interpreter != null) {
- interpreter.close();
- }
- }
- }
-}
-
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
deleted file mode 100644
index dddbb2d618a..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JPythonInjection.qhelp
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
Python has been the most widely used programming language in recent years, and JPython
- is a popular Java implementation of Python. It allows embedded Python scripting inside
- Java applications and provides an interactive interpreter that can be used to interact
- with Java packages or with running Java applications. If an expression is built using
- attacker-controlled data and then evaluated, it may allow the attacker to run arbitrary
- code.
-
-
-
-
In general, including user input in JPython expression should be avoided. If user input
- must be included in an expression, it should be then evaluated in a safe context that
- doesn't allow arbitrary code invocation.
-
-
-
-
The following code could execute random code in JPython Interpreter
Python has been the most widely used programming language in recent years, and Jython
+ (formerly known as JPython) is a popular Java implementation of Python. It allows
+ embedded Python scripting inside Java applications and provides an interactive interpreter
+ that can be used to interact with Java packages or with running Java applications. If an
+ expression is built using attacker-controlled data and then evaluated, it may allow the
+ attacker to run arbitrary code.
+
+
+
+
In general, including user input in Jython expression should be avoided. If user input
+ must be included in an expression, it should be then evaluated in a safe context that
+ doesn't allow arbitrary code invocation.
+
+
+
+
The following code could execute arbitrary code in Jython Interpreter
+
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
new file mode 100644
index 00000000000..088c33e00fd
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
@@ -0,0 +1,123 @@
+/**
+ * @name Injection in Jython
+ * @description Evaluation of a user-controlled malicious expression in Java Python
+ * interpreter may lead to remote code execution.
+ * @kind path-problem
+ * @id java/jython-injection
+ * @tags security
+ * external/cwe/cwe-094
+ * external/cwe/cwe-095
+ */
+
+import java
+import semmle.code.java.dataflow.FlowSources
+import DataFlow::PathGraph
+
+/** The class `org.python.util.PythonInterpreter`. */
+class PythonInterpreter extends RefType {
+ PythonInterpreter() { this.hasQualifiedName("org.python.util", "PythonInterpreter") }
+}
+
+/** A method that evaluates, compiles or executes a Jython expression. */
+class InterpretExprMethod extends Method {
+ InterpretExprMethod() {
+ this.getDeclaringType().getAnAncestor*() instanceof PythonInterpreter and
+ (
+ getName().matches("exec%") or
+ hasName("eval") or
+ hasName("compile") or
+ getName().matches("run%")
+ )
+ }
+}
+
+/** The class `org.python.core.BytecodeLoader`. */
+class BytecodeLoader extends RefType {
+ BytecodeLoader() { this.hasQualifiedName("org.python.core", "BytecodeLoader") }
+}
+
+/** Holds if a Jython expression if evaluated, compiled or executed. */
+predicate runCode(MethodAccess ma, Expr sink) {
+ exists(Method m | m = ma.getMethod() |
+ m instanceof InterpretExprMethod and
+ sink = ma.getArgument(0)
+ )
+}
+
+/** A method that loads Java class data. */
+class LoadClassMethod extends Method {
+ LoadClassMethod() {
+ this.getDeclaringType().getAnAncestor*() instanceof BytecodeLoader and
+ (
+ hasName("makeClass") or
+ hasName("makeCode")
+ )
+ }
+}
+
+/** Holds if a Java class file is loaded. */
+predicate loadClass(MethodAccess ma, Expr sink) {
+ exists(Method m, int i | m = ma.getMethod() |
+ m instanceof LoadClassMethod and
+ m.getParameter(i).getType() instanceof Array and // makeClass(java.lang.String name, byte[] data, ...)
+ sink = ma.getArgument(i)
+ )
+}
+
+/** The class `org.python.core.Py`. */
+class Py extends RefType {
+ Py() { this.hasQualifiedName("org.python.core", "Py") }
+}
+
+/** A method that compiles code with `Py`. */
+class PyCompileMethod extends Method {
+ PyCompileMethod() {
+ this.getDeclaringType().getAnAncestor*() instanceof Py and
+ getName().matches("compile%")
+ }
+}
+
+/** Holds if source code is compiled with `PyCompileMethod`. */
+predicate compile(MethodAccess ma, Expr sink) {
+ exists(Method m | m = ma.getMethod() |
+ m instanceof PyCompileMethod and
+ sink = ma.getArgument(0)
+ )
+}
+
+/** Sink of an expression loaded by Jython. */
+class CodeInjectionSink extends DataFlow::ExprNode {
+ CodeInjectionSink() {
+ runCode(_, this.getExpr()) or
+ loadClass(_, this.getExpr()) or
+ compile(_, this.getExpr())
+ }
+
+ MethodAccess getMethodAccess() {
+ runCode(result, this.getExpr()) or
+ loadClass(result, this.getExpr()) or
+ compile(result, this.getExpr())
+ }
+}
+
+class CodeInjectionConfiguration extends TaintTracking::Configuration {
+ CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
+
+ override predicate isSource(DataFlow::Node source) {
+ source instanceof RemoteFlowSource
+ or
+ source instanceof LocalUserInput
+ }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
+
+ override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
+ // @RequestBody MyQueryObj query; interpreter.exec(query.getInterpreterCode());
+ exists(MethodAccess ma | ma.getQualifier() = node1.asExpr() and ma = node2.asExpr())
+ }
+}
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, CodeInjectionConfiguration conf
+where conf.hasFlowPath(source, sink)
+select sink.getNode().(CodeInjectionSink).getMethodAccess(), source, sink, "Jython evaluate $@.",
+ source.getNode(), "user input"
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
deleted file mode 100644
index f5816001939..00000000000
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.expected
+++ /dev/null
@@ -1,11 +0,0 @@
-edges
-| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code |
-| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code |
-nodes
-| JPythonInjection.java:22:23:22:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| JPythonInjection.java:30:28:30:31 | code | semmle.label | code |
-| JPythonInjection.java:47:21:47:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| JPythonInjection.java:52:40:52:43 | code | semmle.label | code |
-#select
-| JPythonInjection.java:30:11:30:32 | exec(...) | JPythonInjection.java:22:23:22:50 | getParameter(...) : String | JPythonInjection.java:30:28:30:31 | code | JPython evaluate $@. | JPythonInjection.java:22:23:22:50 | getParameter(...) | user input |
-| JPythonInjection.java:52:23:52:44 | eval(...) | JPythonInjection.java:47:21:47:48 | getParameter(...) : String | JPythonInjection.java:52:40:52:43 | code | JPython evaluate $@. | JPythonInjection.java:47:21:47:48 | getParameter(...) | user input |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
deleted file mode 100644
index a0515eb4212..00000000000
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.java
+++ /dev/null
@@ -1,64 +0,0 @@
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.python.core.PyObject;
-import org.python.core.PyException;
-import org.python.util.PythonInterpreter;
-
-public class JPythonInjection extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- public JPythonInjection() {
- super();
- }
-
- // BAD: allow arbitrary JPython expression to execute
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/plain");
- String code = request.getParameter("code");
- PythonInterpreter interpreter = null;
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- try {
- interpreter = new PythonInterpreter();
- interpreter.setOut(out);
- interpreter.setErr(out);
- interpreter.exec(code);
- out.flush();
-
- response.getWriter().print(out.toString());
- } catch(PyException ex) {
- response.getWriter().println(ex.getMessage());
- } finally {
- if (interpreter != null) {
- interpreter.close();
- }
- out.close();
- }
- }
-
- // BAD: allow arbitrary JPython expression to evaluate
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/plain");
- String code = request.getParameter("code");
- PythonInterpreter interpreter = null;
-
- try {
- interpreter = new PythonInterpreter();
- PyObject py = interpreter.eval(code);
-
- response.getWriter().print(py.toString());
- } catch(PyException ex) {
- response.getWriter().println(ex.getMessage());
- } finally {
- if (interpreter != null) {
- interpreter.close();
- }
- }
- }
-}
-
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
deleted file mode 100644
index 80217a193bd..00000000000
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JPythonInjection.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE/CWE-094/JPythonInjection.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.expected
new file mode 100644
index 00000000000..4f66cc83fbd
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.expected
@@ -0,0 +1,21 @@
+edges
+| JythonInjection.java:28:23:28:50 | getParameter(...) : String | JythonInjection.java:36:30:36:33 | code |
+| JythonInjection.java:53:23:53:50 | getParameter(...) : String | JythonInjection.java:58:44:58:47 | code |
+| JythonInjection.java:73:23:73:50 | getParameter(...) : String | JythonInjection.java:81:35:81:38 | code |
+| JythonInjection.java:97:23:97:50 | getParameter(...) : String | JythonInjection.java:106:61:106:75 | getBytes(...) |
+nodes
+| JythonInjection.java:28:23:28:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JythonInjection.java:36:30:36:33 | code | semmle.label | code |
+| JythonInjection.java:53:23:53:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JythonInjection.java:58:44:58:47 | code | semmle.label | code |
+| JythonInjection.java:73:23:73:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JythonInjection.java:81:35:81:38 | code | semmle.label | code |
+| JythonInjection.java:97:23:97:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| JythonInjection.java:106:61:106:75 | getBytes(...) | semmle.label | getBytes(...) |
+| JythonInjection.java:131:40:131:63 | getInputStream(...) | semmle.label | getInputStream(...) |
+#select
+| JythonInjection.java:36:13:36:34 | exec(...) | JythonInjection.java:28:23:28:50 | getParameter(...) : String | JythonInjection.java:36:30:36:33 | code | Jython evaluate $@. | JythonInjection.java:28:23:28:50 | getParameter(...) | user input |
+| JythonInjection.java:58:27:58:48 | eval(...) | JythonInjection.java:53:23:53:50 | getParameter(...) : String | JythonInjection.java:58:44:58:47 | code | Jython evaluate $@. | JythonInjection.java:53:23:53:50 | getParameter(...) | user input |
+| JythonInjection.java:81:13:81:39 | runsource(...) | JythonInjection.java:73:23:73:50 | getParameter(...) : String | JythonInjection.java:81:35:81:38 | code | Jython evaluate $@. | JythonInjection.java:73:23:73:50 | getParameter(...) | user input |
+| JythonInjection.java:106:29:106:134 | makeCode(...) | JythonInjection.java:97:23:97:50 | getParameter(...) : String | JythonInjection.java:106:61:106:75 | getBytes(...) | Jython evaluate $@. | JythonInjection.java:97:23:97:50 | getParameter(...) | user input |
+| JythonInjection.java:131:29:131:109 | compile(...) | JythonInjection.java:131:40:131:63 | getInputStream(...) | JythonInjection.java:131:40:131:63 | getInputStream(...) | Jython evaluate $@. | JythonInjection.java:131:40:131:63 | getInputStream(...) | user input |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
new file mode 100644
index 00000000000..682e8af5113
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
@@ -0,0 +1,144 @@
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.python.core.BytecodeLoader;
+import org.python.core.Py;
+import org.python.core.PyCode;
+import org.python.core.PyException;
+import org.python.core.PyObject;
+import org.python.util.InteractiveInterpreter;
+import org.python.util.PythonInterpreter;
+
+public class JythonInjection extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public JythonInjection() {
+ super();
+ }
+
+ // BAD: allow arbitrary Jython expression to execute
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new PythonInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+ interpreter.exec(code);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ out.close();
+ }
+ }
+
+ // BAD: allow arbitrary Jython expression to evaluate
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+
+ try {
+ interpreter = new PythonInterpreter();
+ PyObject py = interpreter.eval(code);
+
+ response.getWriter().print(py.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+
+ // BAD: allow arbitrary Jython expression to run
+ protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ InteractiveInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new InteractiveInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+ interpreter.runsource(code);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+
+ // BAD: load arbitrary class file to execute
+ protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ PythonInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new PythonInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+
+ PyCode pyCode = BytecodeLoader.makeCode("test", code.getBytes(), getServletContext().getRealPath("/com/example/test.pyc"));
+ interpreter.exec(pyCode);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+
+ // BAD: Compile Python code to execute
+ protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ PythonInterpreter interpreter = null;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ try {
+ interpreter = new PythonInterpreter();
+ interpreter.setOut(out);
+ interpreter.setErr(out);
+
+ PyCode pyCode = Py.compile(request.getInputStream(), "Test.py", org.python.core.CompileMode.eval);
+ interpreter.exec(pyCode);
+ out.flush();
+
+ response.getWriter().print(out.toString());
+ } catch(PyException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ if (interpreter != null) {
+ interpreter.close();
+ }
+ }
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.qlref
new file mode 100644
index 00000000000..0ba9fd60621
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-094/JythonInjection.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/options b/java/ql/test/experimental/query-tests/security/CWE-094/options
index ccf3a24f215..95bc9acaa08 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/options
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/options
@@ -1,2 +1,2 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jpython-2.7.2
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/antlr/base/mod.java b/java/ql/test/stubs/jython-2.7.2/org/python/antlr/base/mod.java
new file mode 100644
index 00000000000..785212f62fa
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/antlr/base/mod.java
@@ -0,0 +1,5 @@
+// Autogenerated AST node
+package org.python.antlr.base;
+
+public abstract class mod {
+}
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/core/BytecodeLoader.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/BytecodeLoader.java
new file mode 100644
index 00000000000..e414216ed03
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/core/BytecodeLoader.java
@@ -0,0 +1,47 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+import java.util.List;
+
+/**
+ * Utility class for loading compiled Python modules and Java classes defined in Python modules.
+ */
+public class BytecodeLoader {
+
+ /**
+ * Turn the Java class file data into a Java class.
+ *
+ * @param name fully-qualified binary name of the class
+ * @param data a class file as a byte array
+ * @param referents super-classes and interfaces that the new class will reference.
+ */
+ @SuppressWarnings("unchecked")
+ public static Class> makeClass(String name, byte[] data, Class>... referents) {
+ return null;
+ }
+
+ /**
+ * Turn the Java class file data into a Java class.
+ *
+ * @param name the name of the class
+ * @param referents super-classes and interfaces that the new class will reference.
+ * @param data a class file as a byte array
+ */
+ public static Class> makeClass(String name, List> referents, byte[] data) {
+ return null;
+ }
+
+ /**
+ * Turn the Java class file data for a compiled Python module into a {@code PyCode} object, by
+ * constructing an instance of the named class and calling the instance's
+ * {@link PyRunnable#getMain()}.
+ *
+ * @param name fully-qualified binary name of the class
+ * @param data a class file as a byte array
+ * @param filename to provide to the constructor of the named class
+ * @return the {@code PyCode} object produced by the named class' {@code getMain}
+ */
+ public static PyCode makeCode(String name, byte[] data, String filename) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/core/CompileMode.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/CompileMode.java
new file mode 100644
index 00000000000..cf7ad1e7201
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/core/CompileMode.java
@@ -0,0 +1,11 @@
+package org.python.core;
+
+public enum CompileMode {
+ eval,
+ single,
+ exec;
+
+ public static CompileMode getMode(String mode) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/core/CompilerFlags.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/CompilerFlags.java
new file mode 100644
index 00000000000..916b93c84ea
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/core/CompilerFlags.java
@@ -0,0 +1,17 @@
+// At some future point this will also be extended - in conjunction with
+// Py#compileFlags - to add
+// support for a compiler factory that user code can choose in place of the
+// normal compiler.
+// (Perhaps a better name might have been "CompilerOptions".)
+
+package org.python.core;
+
+import java.io.Serializable;
+
+public class CompilerFlags implements Serializable {
+ public CompilerFlags() {
+ }
+
+ public CompilerFlags(int co_flags) {
+ }
+}
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/core/Py.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/Py.java
new file mode 100644
index 00000000000..cc0c9f1e4bd
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/core/Py.java
@@ -0,0 +1,134 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.core;
+
+import java.io.InputStream;
+import java.io.Serializable;
+
+import org.python.antlr.base.mod;
+
+public final class Py {
+ /**
+ Convert a given PyObject to an instance of a Java class.
+ Identical to o.__tojava__(c) except that it will
+ raise a TypeError if the conversion fails.
+ @param o the PyObject to convert.
+ @param c the class to convert it to.
+ **/
+ @SuppressWarnings("unchecked")
+ public static T tojava(PyObject o, Class c) {
+ return null;
+ }
+
+ // ??pending: was @deprecated but is actually used by proxie code.
+ // Can get rid of it?
+ public static Object tojava(PyObject o, String s) {
+ return null;
+ }
+
+ /**
+ * Uses the PyObjectAdapter passed to {@link PySystemState#initialize} to turn o into a PyObject.
+ *
+ * @see ClassicPyObjectAdapter - default PyObjectAdapter type
+ */
+ public static PyObject java2py(Object o) {
+ return null;
+ }
+
+ /**
+ * Uses the PyObjectAdapter passed to {@link PySystemState#initialize} to turn
+ * objects into an array of PyObjects.
+ *
+ * @see ClassicPyObjectAdapter - default PyObjectAdapter type
+ */
+ public static PyObject[] javas2pys(Object... objects) {
+ return null;
+ }
+
+ public static PyObject makeClass(String name, PyObject[] bases, PyCode code,
+ PyObject[] closure_cells) {
+ return null;
+ }
+
+ public static PyObject makeClass(String name, PyObject base, PyObject dict) {
+ return null;
+ }
+
+ /**
+ * Create a new Python class.
+ *
+ * @param name the String name of the class
+ * @param bases an array of PyObject base classes
+ * @param dict the class's namespace, containing the class body
+ * definition
+ * @return a new Python Class PyObject
+ */
+ public static PyObject makeClass(String name, PyObject[] bases, PyObject dict) {
+ return null;
+ }
+
+ public static CompilerFlags getCompilerFlags() {
+ return null;
+ }
+
+ public static CompilerFlags getCompilerFlags(int flags, boolean dont_inherit) {
+ return null;
+ }
+
+ public static CompilerFlags getCompilerFlags(CompilerFlags flags, boolean dont_inherit) {
+ return null;
+ }
+
+ // w/o compiler-flags
+ public static PyCode compile(InputStream istream, String filename, CompileMode kind) {
+ return null;
+ }
+
+ /**
+ * Entry point for compiling modules.
+ *
+ * @param node Module node, coming from the parsing process
+ * @param name Internal name for the compiled code. Typically generated by
+ * calling {@link #getName()}.
+ * @param filename Source file name
+ * @param linenumbers True to track source line numbers on the generated
+ * code
+ * @param printResults True to call the sys.displayhook on the result of
+ * the code
+ * @param cflags Compiler flags
+ * @return Code object for the compiled module
+ */
+ public static PyCode compile_flags(mod node, String name, String filename,
+ boolean linenumbers, boolean printResults,
+ CompilerFlags cflags) {
+ return null;
+ }
+
+ public static PyCode compile_flags(mod node, String filename,
+ CompileMode kind, CompilerFlags cflags) {
+ return null;
+ }
+
+ /**
+ * Compiles python source code coming from a file or another external stream
+ */
+ public static PyCode compile_flags(InputStream istream, String filename,
+ CompileMode kind, CompilerFlags cflags) {
+ return null;
+ }
+
+ /**
+ * Compiles python source code coming from String (raw bytes) data.
+ *
+ * If the String is properly decoded (from PyUnicode) the PyCF_SOURCE_IS_UTF8 flag
+ * should be specified.
+ */
+ public static PyCode compile_flags(String data, String filename,
+ CompileMode kind, CompilerFlags cflags) {
+ return null;
+ }
+
+ public static PyObject compile_command_flags(String string, String filename,
+ CompileMode kind, CompilerFlags cflags, boolean stdprompt) {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/PyCode.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/core/PyCode.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/core/PyCode.java
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/PyException.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/core/PyException.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/core/PyException.java
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/PyObject.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/core/PyObject.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/core/PyObject.java
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/PySystemState.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/core/PySystemState.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/core/PySystemState.java
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java b/java/ql/test/stubs/jython-2.7.2/org/python/core/ThreadState.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/core/ThreadState.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/core/ThreadState.java
diff --git a/java/ql/test/stubs/jython-2.7.2/org/python/util/InteractiveInterpreter.java b/java/ql/test/stubs/jython-2.7.2/org/python/util/InteractiveInterpreter.java
new file mode 100644
index 00000000000..b12fa617227
--- /dev/null
+++ b/java/ql/test/stubs/jython-2.7.2/org/python/util/InteractiveInterpreter.java
@@ -0,0 +1,114 @@
+// Copyright (c) Corporation for National Research Initiatives
+package org.python.util;
+
+import org.python.core.*;
+
+/**
+ * This class provides the interface for compiling and running code that supports an interactive
+ * interpreter.
+ */
+// Based on CPython-1.5.2's code module
+public class InteractiveInterpreter extends PythonInterpreter {
+
+ /**
+ * Construct an InteractiveInterpreter with all default characteristics: default state (from
+ * {@link Py#getSystemState()}), and a new empty dictionary of local variables.
+ * */
+ public InteractiveInterpreter() {
+ }
+
+ /**
+ * Construct an InteractiveInterpreter with state (from {@link Py#getSystemState()}), and the
+ * specified dictionary of local variables.
+ *
+ * @param locals dictionary to use, or if null, a new empty one will be created
+ */
+ public InteractiveInterpreter(PyObject locals) {
+ }
+
+ /**
+ * Construct an InteractiveInterpreter with, and system state the specified dictionary of local
+ * variables.
+ *
+ * @param locals dictionary to use, or if null, a new empty one will be created
+ * @param systemState interpreter state, or if null use {@link Py#getSystemState()}
+ */
+ public InteractiveInterpreter(PyObject locals, PySystemState systemState) {
+ }
+
+ /**
+ * Compile and run some source in the interpreter, in the mode {@link CompileMode#single} which
+ * is used for incremental compilation at the interactive console, known as {@code }.
+ *
+ * @param source Python code
+ * @return true to indicate a partial statement was entered
+ */
+ public boolean runsource(String source) {
+ return false;
+ }
+
+ /**
+ * Compile and run some source in the interpreter, in the mode {@link CompileMode#single} which
+ * is used for incremental compilation at the interactive console.
+ *
+ * @param source Python code
+ * @param filename name with which to label this console input (e.g. in error messages).
+ * @return true to indicate a partial statement was entered
+ */
+ public boolean runsource(String source, String filename) {
+ return false;
+ }
+
+ /**
+ * Compile and run some source in the interpreter, according to the {@link CompileMode} given.
+ * This method supports incremental compilation and interpretation through the return value,
+ * where {@code true} signifies that more input is expected in order to complete the Python
+ * statement. An interpreter can use this to decide whether to use {@code sys.ps1}
+ * ("{@code >>> }") or {@code sys.ps2} ("{@code ... }") to prompt the next line. The arguments
+ * are the same as the mandatory ones in the Python {@code compile()} command.
+ *
+ * One the following can happen:
+ *
+ *
The input is incorrect; compilation raised an exception (SyntaxError or OverflowError). A
+ * syntax traceback will be printed by calling {@link #showexception(PyException)}. Return is
+ * {@code false}.
+ *
+ *
The input is incomplete, and more input is required; compilation returned no code.
+ * Nothing happens. Return is {@code true}.
+ *
+ *
The input is complete; compilation returned a code object. The code is executed by
+ * calling {@link #runcode(PyObject)} (which also handles run-time exceptions, except for
+ * SystemExit). Return is {@code false}.
+ *
+ *
+ * @param source Python code
+ * @param filename name with which to label this console input (e.g. in error messages).
+ * @param kind of compilation required: {@link CompileMode#eval}, {@link CompileMode#exec} or
+ * {@link CompileMode#single}
+ * @return {@code true} to indicate a partial statement was provided
+ */
+ public boolean runsource(String source, String filename, CompileMode kind) {
+ return false;
+ }
+
+ /**
+ * Execute a code object. When an exception occurs, {@link #showexception(PyException)} is
+ * called to display a stack trace, except in the case of SystemExit, which is re-raised.
+ *
+ * A note about KeyboardInterrupt: this exception may occur elsewhere in this code, and may not
+ * always be caught. The caller should be prepared to deal with it.
+ **/
+
+ // Make this run in another thread somehow????
+ public void runcode(PyObject code) {
+ }
+
+ public void showexception(PyException exc) {
+ }
+
+ public void write(String data) {
+ }
+
+ public void resetbuffer() {
+ }
+}
diff --git a/java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java b/java/ql/test/stubs/jython-2.7.2/org/python/util/PythonInterpreter.java
similarity index 100%
rename from java/ql/test/stubs/jpython-2.7.2/org/python/util/PythonInterpreter.java
rename to java/ql/test/stubs/jython-2.7.2/org/python/util/PythonInterpreter.java
From b277082462848f3b102fac3c4f79e9babe8b4048 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Wed, 5 May 2021 23:28:04 +0300
Subject: [PATCH 089/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
---
.../DeclarationOfVariableWithUnnecessarilyWideScope.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
index d84f47f5453..5234212f7ca 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.qhelp
@@ -3,7 +3,7 @@
"qhelp.dtd">
-
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.
+
Using variables with the same name is dangerous. However, such a situation inside the while loop can create an infinite loop exhausting resources. Requires the attention of developers.
From 976ccda135748f5fff12250eed60f02e14d9aab3 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Wed, 5 May 2021 23:34:21 +0300
Subject: [PATCH 090/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.ql
---
.../DeclarationOfVariableWithUnnecessarilyWideScope.ql | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
index 9acc1d35d81..be712b1cb1d 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
@@ -1,7 +1,7 @@
/**
* @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.
+ * However, such a situation inside the while loop can create an infinite loop exhausting resources.
* Requires the attention of developers.
* @kind problem
* @id cpp/errors-when-using-variable-declaration-inside-loop
@@ -37,7 +37,7 @@ class DangerousWhileLoop extends WhileStmt {
/** Holds when there are changes to the variables involved in the condition. */
predicate isUseThisVariable() {
exists(Variable v |
- this.getCondition().getAChild*().(VariableAccess).getTarget() = v and
+ exp.(VariableAccess).getTarget() = v and
(
exists(Assignment aexp |
aexp = this.getStmt().getAChild*() and
From 67e9f063047d5040f73f21f641270e07a8a3a144 Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Wed, 5 May 2021 17:27:49 -0400
Subject: [PATCH 091/168] [Java] Fix Kryo FP & Kryo 5 Support
Closes #4992
---
.../2021-05-05-kryo-improvements.md | 3 +
.../code/java/dataflow/ExternalFlow.qll | 1 +
.../src/semmle/code/java/frameworks/Kryo.qll | 55 ++++++++++++++++-
.../java/security/UnsafeDeserialization.qll | 59 +++++++++++++++++++
.../security/CWE-502/KryoTest.java | 34 +++++++++++
.../kryo/pool/KryoCallback.java | 7 +++
.../kryo/pool/KryoFactory.java | 7 +++
.../esotericsoftware/kryo/pool/KryoPool.java | 30 ++++++++++
8 files changed, 194 insertions(+), 2 deletions(-)
create mode 100644 java/change-notes/2021-05-05-kryo-improvements.md
create mode 100644 java/ql/test/query-tests/security/CWE-502/KryoTest.java
create mode 100644 java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoCallback.java
create mode 100644 java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoFactory.java
create mode 100644 java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoPool.java
diff --git a/java/change-notes/2021-05-05-kryo-improvements.md b/java/change-notes/2021-05-05-kryo-improvements.md
new file mode 100644
index 00000000000..f8ba79eb863
--- /dev/null
+++ b/java/change-notes/2021-05-05-kryo-improvements.md
@@ -0,0 +1,3 @@
+lgtm,codescanning
+* Add support for version 5 of the Kryo serialzation/deserialization framework.
+* Add support for detecting safe uses of Kryo utilizing `KryoPool.Builder. (#4992)[https://github.com/github/codeql/issues/4992]
diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
index 7073c57ff9c..b62018dc2c4 100644
--- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
+++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
@@ -291,6 +291,7 @@ private predicate summaryModelCsv(string row) {
"java.util;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
"java.beans;XMLDecoder;false;XMLDecoder;;;Argument[0];Argument[-1];taint",
"com.esotericsoftware.kryo.io;Input;false;Input;;;Argument[0];Argument[-1];taint",
+ "com.esotericsoftware.kryo5.io;Input;false;Input;;;Argument[0];Argument[-1];taint",
"java.io;BufferedInputStream;false;BufferedInputStream;;;Argument[0];Argument[-1];taint",
"java.io;DataInputStream;false;DataInputStream;;;Argument[0];Argument[-1];taint",
"java.io;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint",
diff --git a/java/ql/src/semmle/code/java/frameworks/Kryo.qll b/java/ql/src/semmle/code/java/frameworks/Kryo.qll
index 049be97ea9c..16873fc751f 100644
--- a/java/ql/src/semmle/code/java/frameworks/Kryo.qll
+++ b/java/ql/src/semmle/code/java/frameworks/Kryo.qll
@@ -3,19 +3,60 @@
*/
import java
+private import semmle.code.java.dataflow.DataFlow
+private import semmle.code.java.dataflow.FlowSteps
/**
* The type `com.esotericsoftware.kryo.Kryo`.
*/
class Kryo extends RefType {
- Kryo() { this.hasQualifiedName("com.esotericsoftware.kryo", "Kryo") }
+ Kryo() {
+ hasQualifiedName("com.esotericsoftware.kryo", "Kryo") or
+ hasQualifiedName("com.esotericsoftware.kryo5", "Kryo")
+ }
}
/**
* A Kryo input stream.
*/
class KryoInput extends RefType {
- KryoInput() { this.hasQualifiedName("com.esotericsoftware.kryo.io", "Input") }
+ KryoInput() {
+ hasQualifiedName("com.esotericsoftware.kryo.io", "Input") or
+ hasQualifiedName("com.esotericsoftware.kryo5.io", "Input")
+ }
+}
+
+/**
+ * A Kryo pool.
+ */
+class KryoPool extends RefType {
+ KryoPool() {
+ hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool") or
+ hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool")
+ }
+}
+
+/**
+ * A Kryo pool builder.
+ */
+class KryoPoolBuilder extends RefType {
+ KryoPoolBuilder() {
+ hasQualifiedName("com.esotericsoftware.kryo.pool", "KryoPool$Builder") or
+ hasQualifiedName("com.esotericsoftware.kryo5.pool", "KryoPool$Builder")
+ }
+}
+
+/**
+ * A Kryo pool builder method used a fluent API call chain.
+ */
+class KryoPoolBuilderMethod extends Method {
+ KryoPoolBuilderMethod() {
+ getDeclaringType() instanceof KryoPoolBuilder and
+ (
+ getReturnType() instanceof KryoPoolBuilder or
+ getReturnType() instanceof KryoPool
+ )
+ }
}
/**
@@ -45,3 +86,13 @@ class KryoEnableWhiteListing extends MethodAccess {
)
}
}
+
+/**
+ * A KryoPool method that uses a Kryo instance.
+ */
+class KryoPoolRunMethod extends Method {
+ KryoPoolRunMethod() {
+ getDeclaringType() instanceof KryoPool and
+ hasName("run")
+ }
+}
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index ab809f07d6d..def37c0964e 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -48,6 +48,65 @@ class SafeKryo extends DataFlow2::Configuration {
ma.getMethod() instanceof KryoReadObjectMethod
)
}
+
+ override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or
+ stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or
+ stepKryoPoolBuilderChainMethod(node1, node2) or
+ stepKryoPoolBorrowMethod(node1, node2)
+ }
+
+ /**
+ * Holds when a funcitonal expression is used to create a `KryoPool.Builder`.
+ * Eg. `new KryoPool.Builder(() -> new Kryo())`
+ */
+ private predicate stepKryoPoolBuilderFactoryArgToConstructor(
+ DataFlow::Node node1, DataFlow::Node node2
+ ) {
+ exists(ConstructorCall cc, FunctionalExpr fe |
+ cc.getConstructedType() instanceof KryoPoolBuilder and
+ fe.asMethod().getBody().getAStmt().(ReturnStmt).getResult() = node1.asExpr() and
+ node2.asExpr() = cc and
+ cc.getArgument(0) = fe
+ )
+ }
+
+ /**
+ * Holds when a `KryoPool.run` is called to use a `Kryo` instance.
+ * Eg. `pool.run(kryo -> ...)`
+ */
+ private predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(
+ DataFlow::Node node1, DataFlow::Node node2
+ ) {
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof KryoPoolRunMethod and
+ node1.asExpr() = ma.getQualifier() and
+ ma.getArgument(0).(FunctionalExpr).asMethod().getParameter(0) = node2.asParameter()
+ )
+ }
+
+ /**
+ * Holds when a `KryoPool.Builder` method is called fluently.
+ */
+ private predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) {
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof KryoPoolBuilderMethod and
+ ma = node2.asExpr() and
+ ma.getQualifier() = node1.asExpr()
+ )
+ }
+
+ /**
+ * Holds when a `KryoPool.borrow` method is called.
+ */
+ private predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) {
+ exists(MethodAccess ma |
+ ma.getMethod() =
+ any(Method m | m.getDeclaringType() instanceof KryoPool and m.hasName("borrow")) and
+ node1.asExpr() = ma.getQualifier() and
+ node2.asExpr() = ma
+ )
+ }
}
predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
diff --git a/java/ql/test/query-tests/security/CWE-502/KryoTest.java b/java/ql/test/query-tests/security/CWE-502/KryoTest.java
new file mode 100644
index 00000000000..8890bad91b9
--- /dev/null
+++ b/java/ql/test/query-tests/security/CWE-502/KryoTest.java
@@ -0,0 +1,34 @@
+
+import java.io.*;
+import java.net.Socket;
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.pool.KryoPool;
+import com.esotericsoftware.kryo.io.Input;
+
+public class KryoTest {
+
+ private Kryo getSafeKryo() {
+ Kryo kryo = new Kryo();
+ kryo.setRegistrationRequired(true);
+ // ... kryo.register(A.class) ...
+ return kryo;
+ }
+
+ public void kryoDeserialize(Socket sock) throws java.io.IOException {
+ KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
+ Input input = new Input(sock.getInputStream());
+ Object o = kryoPool.run(kryo -> kryo.readClassAndObject(input)); // OK
+ }
+
+ public void kryoDeserialize2(Socket sock) throws java.io.IOException {
+ KryoPool kryoPool = new KryoPool.Builder(this::getSafeKryo).softReferences().build();
+ Input input = new Input(sock.getInputStream());
+ Kryo k = kryoPool.borrow();
+ try {
+ Object o = k.readClassAndObject(input); // OK
+ } finally {
+ kryoPool.release(k);
+ }
+ }
+
+}
diff --git a/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoCallback.java b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoCallback.java
new file mode 100644
index 00000000000..729426aba62
--- /dev/null
+++ b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoCallback.java
@@ -0,0 +1,7 @@
+package com.esotericsoftware.kryo.pool;
+
+import com.esotericsoftware.kryo.Kryo;
+
+public interface KryoCallback {
+ T execute (Kryo kryo);
+}
diff --git a/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoFactory.java b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoFactory.java
new file mode 100644
index 00000000000..4dcda1445df
--- /dev/null
+++ b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoFactory.java
@@ -0,0 +1,7 @@
+package com.esotericsoftware.kryo.pool;
+
+import com.esotericsoftware.kryo.Kryo;
+
+public interface KryoFactory {
+ Kryo create ();
+}
diff --git a/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoPool.java b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoPool.java
new file mode 100644
index 00000000000..c005442c9e8
--- /dev/null
+++ b/java/ql/test/stubs/kryo-4.0.2/com/esotericsoftware/kryo/pool/KryoPool.java
@@ -0,0 +1,30 @@
+package com.esotericsoftware.kryo.pool;
+
+import com.esotericsoftware.kryo.Kryo;
+import java.util.Queue;
+
+public interface KryoPool {
+
+ Kryo borrow ();
+
+ void release (Kryo kryo);
+
+ T run (KryoCallback callback);
+
+ static class Builder {
+ public Builder (KryoFactory factory) {
+ }
+
+ public Builder queue (Queue queue) {
+ return null;
+ }
+
+ public Builder softReferences () {
+ return null;
+ }
+
+ public KryoPool build () {
+ return null;
+ }
+ }
+}
From df5eab33f946ed0b88da4287f24659e01ab6e399 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Mon, 10 May 2021 09:43:33 +0100
Subject: [PATCH 092/168] JS: Update relevantTaintSource()
---
javascript/ql/src/meta/internal/TaintMetrics.qll | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/javascript/ql/src/meta/internal/TaintMetrics.qll b/javascript/ql/src/meta/internal/TaintMetrics.qll
index 6d10b2c6ad6..f6eae2eaa6e 100644
--- a/javascript/ql/src/meta/internal/TaintMetrics.qll
+++ b/javascript/ql/src/meta/internal/TaintMetrics.qll
@@ -75,16 +75,9 @@ DataFlow::Node relevantTaintSink(string kind) {
DataFlow::Node relevantTaintSink() { result = relevantTaintSink(_) }
/**
- * Gets a remote flow source or `document.location` source.
+ * Gets a relevant remote flow source.
*/
-DataFlow::Node relevantTaintSource() {
- not result.getFile() instanceof IgnoredFile and
- (
- result instanceof RemoteFlowSource
- or
- result = DOM::locationSource()
- )
-}
+RemoteFlowSource relevantTaintSource() { not result.getFile() instanceof IgnoredFile }
/**
* Gets the output of a call that shows intent to sanitize a value
From c8f2937df9bd4d990f0cf654161319c668475e13 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Mon, 10 May 2021 14:16:11 +0300
Subject: [PATCH 093/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.ql
---
.../DeclarationOfVariableWithUnnecessarilyWideScope.ql | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
index be712b1cb1d..e73f36145c6 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
@@ -27,8 +27,6 @@ class DangerousWhileLoop extends WhileStmt {
not exp instanceof PointerFieldAccess and
not exp instanceof ValueFieldAccess and
exp.(VariableAccess).getTarget().getName() = dl.getName() and
- not exp.getParent*() instanceof CrementOperation and
- not exp.getParent*() instanceof Assignment and
not exp.getParent*() instanceof FunctionCall
}
@@ -37,10 +35,10 @@ class DangerousWhileLoop extends WhileStmt {
/** Holds when there are changes to the variables involved in the condition. */
predicate isUseThisVariable() {
exists(Variable v |
- exp.(VariableAccess).getTarget() = v and
+ this.getCondition().getAChild*().(VariableAccess).getTarget() = v and
(
exists(Assignment aexp |
- aexp = this.getStmt().getAChild*() and
+ this = aexp.getEnclosingStmt().getParentStmt*() and
(
aexp.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v
or
@@ -49,7 +47,7 @@ class DangerousWhileLoop extends WhileStmt {
)
or
exists(CrementOperation crm |
- crm = this.getStmt().getAChild*() and
+ this = crm.getEnclosingStmt().getParentStmt*() and
crm.getOperand().(VariableAccess).getTarget() = v
)
)
@@ -59,4 +57,4 @@ class DangerousWhileLoop extends WhileStmt {
from DangerousWhileLoop lp
where not lp.isUseThisVariable()
-select lp.getDeclaration(), "A variable with this name is used in the loop condition."
+select lp.getDeclaration(), "A variable with this name is used in the $@ condition.", lp, "loop"
From d3c6093f37d14861a10cf1ef2134c8bc183340d7 Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Mon, 10 May 2021 14:16:38 +0300
Subject: [PATCH 094/168] Update test.c
---
.../Security/CWE/CWE-1126/semmle/tests/test.c | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
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
index 325c278f697..47d89188e6b 100644
--- 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
@@ -1,5 +1,6 @@
void workFunction_0(char *s) {
int intIndex = 10;
+ int intGuard;
char buf[80];
while(intIndex > 2) // GOOD
{
@@ -14,6 +15,32 @@ void workFunction_0(char *s) {
intIndex--;
}
intIndex = 10;
+ intGuard = 20;
+ while(intIndex < intGuard--) // GOOD
+ {
+ buf[intIndex] = 1;
+ int intIndex;
+ intIndex--;
+ }
+ intIndex = 10;
+ intGuard = 20;
+ while(intIndex < intGuard) // GOOD
+ {
+ buf[intIndex] = 1;
+ int intIndex;
+ intIndex++;
+ intGuard--;
+ }
+ intIndex = 10;
+ intGuard = 20;
+ while(intIndex < intGuard) // GOOD
+ {
+ buf[intIndex] = 1;
+ int intIndex;
+ intIndex--;
+ intGuard -= 4;
+ }
+ intIndex = 10;
while(intIndex > 2) // GOOD
{
buf[intIndex] = 1;
From 3e5dc1efb7ea527e8b2d7b8149ce2f5dbc76a2ef Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Mon, 10 May 2021 13:17:25 +0200
Subject: [PATCH 095/168] JS: More robust hasUnderlyingType
---
javascript/ql/src/semmle/javascript/TypeScript.qll | 2 +-
javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll | 1 -
.../TypeScript/HasUnderlyingType/HasUnderlyingType.expected | 4 ++++
.../TypeScript/HasUnderlyingType/HasUnderlyingType.ql | 4 ++++
.../test/library-tests/TypeScript/HasUnderlyingType/foo.ts | 5 +++++
5 files changed, 14 insertions(+), 2 deletions(-)
create mode 100644 javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/foo.ts
diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/src/semmle/javascript/TypeScript.qll
index 4fe263c8389..0b611140449 100644
--- a/javascript/ql/src/semmle/javascript/TypeScript.qll
+++ b/javascript/ql/src/semmle/javascript/TypeScript.qll
@@ -725,7 +725,7 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef {
spec.getImportedName() = exportedName and
this = spec.getLocal().(TypeDecl).getLocalTypeName().getAnAccess()
or
- spec instanceof ImportNamespaceSpecifier and
+ (spec instanceof ImportNamespaceSpecifier or spec instanceof ImportDefaultSpecifier) and
this =
spec.getLocal().(LocalNamespaceDecl).getLocalNamespaceName().getAMemberAccess(exportedName)
)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
index c73c894ca4b..f02e9b0f287 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
@@ -239,7 +239,6 @@ module DataFlow {
private TypeAnnotation getFallbackTypeAnnotation() {
exists(BindingPattern pattern |
this = valueNode(pattern) and
- not ast_node_type(pattern, _) and
result = pattern.getTypeAnnotation()
)
or
diff --git a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected
index 95c6d7e03d9..47e57e0a242 100644
--- a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected
+++ b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.expected
@@ -1,2 +1,6 @@
+underlyingTypeNode
+| foo | Bar | foo.ts:3:1:5:1 | use (instance (member Bar (member exports (module foo)))) |
+| foo | Bar | foo.ts:3:12:3:12 | use (instance (member Bar (member exports (module foo)))) |
+#select
| tst.ts:8:14:8:16 | arg | Base in global scope |
| tst.ts:8:14:8:16 | arg | Sub in global scope |
diff --git a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.ql b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.ql
index 77e311b3b76..72d4e6d0f3d 100644
--- a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.ql
+++ b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/HasUnderlyingType.ql
@@ -3,3 +3,7 @@ import javascript
from Expr e, TypeName typeName
where e.getType().hasUnderlyingTypeName(typeName)
select e, typeName
+
+query API::Node underlyingTypeNode(string mod, string name) {
+ result = API::Node::ofType(mod, name)
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/foo.ts b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/foo.ts
new file mode 100644
index 00000000000..1b5be79068a
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/HasUnderlyingType/foo.ts
@@ -0,0 +1,5 @@
+import foo from "foo";
+
+function f(x: foo.Bar) {
+ return x;
+}
From 9e5a38debd315a8f7ca90c9bcc78d7798b334e5d Mon Sep 17 00:00:00 2001
From: ihsinme
Date: Mon, 10 May 2021 14:17:40 +0300
Subject: [PATCH 096/168] Update
DeclarationOfVariableWithUnnecessarilyWideScope.expected
---
.../DeclarationOfVariableWithUnnecessarilyWideScope.expected | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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
index 4b29dad8779..244a28cf332 100644
--- 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
@@ -1 +1 @@
-| test.c:13:9:13:16 | intIndex | A variable with this name is used in the loop condition. |
+| test.c:14:9:14:16 | intIndex | A variable with this name is used in the $@ condition. | test.c:11:3:16:3 | while (...) ... | loop |
From d6f9e37e3943f689891df1360c651c61c0a403e6 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Mon, 10 May 2021 13:31:00 +0200
Subject: [PATCH 097/168] add printAst.ql support for regular expressions
---
.../ql/src/semmle/javascript/PrintAst.qll | 36 +++-
.../ql/src/semmle/javascript/Regexp.qll | 100 +++++++++--
.../library-tests/TypeScript/Types/dummy.ts | 2 +
.../TypeScript/Types/printAst.expected | 163 +++++++++++-------
.../TypeScript/Types/tests.expected | 2 +
5 files changed, 219 insertions(+), 84 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/PrintAst.qll b/javascript/ql/src/semmle/javascript/PrintAst.qll
index 0499e3bd547..99f06354d74 100644
--- a/javascript/ql/src/semmle/javascript/PrintAst.qll
+++ b/javascript/ql/src/semmle/javascript/PrintAst.qll
@@ -73,7 +73,8 @@ private newtype TPrintAstNode =
THTMLAttributesNodes(HTML::Element e) { shouldPrint(e, _) and not isNotNeeded(e) } or
THTMLAttributeNode(HTML::Attribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
THTMLScript(Script script) { shouldPrint(script, _) and not isNotNeeded(script) } or
- THTMLCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) }
+ THTMLCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
+ TRegExpTermNode(RegExpTerm term) { term.isUsedAsRegExp() }
/**
* A node in the output tree.
@@ -282,6 +283,39 @@ private module PrintJavaScript {
}
}
+ /**
+ * A print node for regexp literals.
+ *
+ * The single child of this node is the root `RegExpTerm`.
+ */
+ class RegexpNode extends ElementNode {
+ override RegExpLiteral element;
+
+ override PrintAstNode getChild(int childIndex) {
+ childIndex = 0 and
+ result.(RegExpTermNode).getTerm() = element.getRoot()
+ }
+ }
+
+ /**
+ * A print node for regexp terms.
+ */
+ class RegExpTermNode extends PrintAstNode, TRegExpTermNode {
+ RegExpTerm term;
+
+ RegExpTermNode() { this = TRegExpTermNode(term) }
+
+ RegExpTerm getTerm() { result = term }
+
+ override PrintAstNode getChild(int childIndex) {
+ result.(RegExpTermNode).getTerm() = term.getChild(childIndex)
+ }
+
+ override string toString() { result = getQlClass(term) + term.toString() }
+
+ override Location getLocation() { result = term.getLocation() }
+ }
+
/**
* An aggregate node representing all the arguments for an function invocation.
*/
diff --git a/javascript/ql/src/semmle/javascript/Regexp.qll b/javascript/ql/src/semmle/javascript/Regexp.qll
index a34b052005d..d3b7e9cac7e 100644
--- a/javascript/ql/src/semmle/javascript/Regexp.qll
+++ b/javascript/ql/src/semmle/javascript/Regexp.qll
@@ -215,7 +215,9 @@ class InfiniteRepetitionQuantifier extends RegExpQuantifier {
* \w
* ```
*/
-class RegExpEscape extends RegExpTerm, @regexp_escape { }
+class RegExpEscape extends RegExpTerm, @regexp_escape {
+ override string getAPrimaryQlClass() { result = "RegExpEscape" }
+}
/**
* A constant regular expression term, that is, a regular expression
@@ -240,6 +242,8 @@ class RegExpConstant extends RegExpTerm, @regexp_constant {
override predicate isNullable() { none() }
override string getConstantValue() { result = getValue() }
+
+ override string getAPrimaryQlClass() { result = "RegExpConstant" }
}
/**
@@ -264,6 +268,8 @@ class RegExpCharEscape extends RegExpEscape, RegExpConstant, @regexp_char_escape
)
)
}
+
+ override string getAPrimaryQlClass() { result = "RegExpCharEscape" }
}
/**
@@ -285,6 +291,8 @@ class RegExpAlt extends RegExpTerm, @regexp_alt {
override predicate isNullable() { getAlternative().isNullable() }
override string getAMatchedString() { result = getAlternative().getAMatchedString() }
+
+ override string getAPrimaryQlClass() { result = "RegExpAlt" }
}
/**
@@ -332,6 +340,8 @@ class RegExpSequence extends RegExpTerm, @regexp_seq {
result = this.getChild(i + 1)
)
}
+
+ override string getAPrimaryQlClass() { result = "RegExpSequence" }
}
/**
@@ -346,6 +356,8 @@ class RegExpSequence extends RegExpTerm, @regexp_seq {
*/
class RegExpAnchor extends RegExpTerm, @regexp_anchor {
override predicate isNullable() { any() }
+
+ override string getAPrimaryQlClass() { result = "RegExpAnchor" }
}
/**
@@ -357,7 +369,9 @@ class RegExpAnchor extends RegExpTerm, @regexp_anchor {
* ^
* ```
*/
-class RegExpCaret extends RegExpAnchor, @regexp_caret { }
+class RegExpCaret extends RegExpAnchor, @regexp_caret {
+ override string getAPrimaryQlClass() { result = "RegExpCaret" }
+}
/**
* A dollar assertion `$` matching the end of a line.
@@ -368,7 +382,9 @@ class RegExpCaret extends RegExpAnchor, @regexp_caret { }
* $
* ```
*/
-class RegExpDollar extends RegExpAnchor, @regexp_dollar { }
+class RegExpDollar extends RegExpAnchor, @regexp_dollar {
+ override string getAPrimaryQlClass() { result = "RegExpDollar" }
+}
/**
* A word boundary assertion.
@@ -381,6 +397,8 @@ class RegExpDollar extends RegExpAnchor, @regexp_dollar { }
*/
class RegExpWordBoundary extends RegExpTerm, @regexp_wordboundary {
override predicate isNullable() { any() }
+
+ override string getAPrimaryQlClass() { result = "RegExpWordBoundary" }
}
/**
@@ -394,6 +412,8 @@ class RegExpWordBoundary extends RegExpTerm, @regexp_wordboundary {
*/
class RegExpNonWordBoundary extends RegExpTerm, @regexp_nonwordboundary {
override predicate isNullable() { any() }
+
+ override string getAPrimaryQlClass() { result = "RegExpNonWordBoundary" }
}
/**
@@ -425,7 +445,9 @@ class RegExpSubPattern extends RegExpTerm, @regexp_subpattern {
* (?!\n)
* ```
*/
-class RegExpLookahead extends RegExpSubPattern, @regexp_lookahead { }
+class RegExpLookahead extends RegExpSubPattern, @regexp_lookahead {
+ override string getAPrimaryQlClass() { result = "RegExpLookahead" }
+}
/**
* A zero-width lookbehind assertion.
@@ -437,7 +459,9 @@ class RegExpLookahead extends RegExpSubPattern, @regexp_lookahead { }
* (?`
@@ -770,6 +832,8 @@ class RegExpBackRef extends RegExpTerm, @regexp_backref {
}
override predicate isNullable() { getGroup().isNullable() }
+
+ override string getAPrimaryQlClass() { result = "RegExpBackRef" }
}
/**
@@ -808,6 +872,8 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase()
)
}
+
+ override string getAPrimaryQlClass() { result = "RegExpCharacterClass" }
}
/**
@@ -827,6 +893,8 @@ class RegExpCharacterRange extends RegExpTerm, @regexp_char_range {
lo = getChild(0).(RegExpConstant).getValue() and
hi = getChild(1).(RegExpConstant).getValue()
}
+
+ override string getAPrimaryQlClass() { result = "RegExpCharacterRange" }
}
/** A parse error encountered while processing a regular expression literal. */
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/dummy.ts b/javascript/ql/test/library-tests/TypeScript/Types/dummy.ts
index 77f17538e18..d36be434986 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/dummy.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/dummy.ts
@@ -1,2 +1,4 @@
// Dummy file to be imported so the other files are seen as modules.
export let x = 5;
+
+export let reg = /ab+c/;
\ No newline at end of file
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
index bd50eaa28ec..1f39b308479 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
@@ -74,6 +74,17 @@ nodes
| dummy.ts:2:12:2:12 | [VarDecl] x | semmle.label | [VarDecl] x |
| dummy.ts:2:12:2:16 | [VariableDeclarator] x = 5 | semmle.label | [VariableDeclarator] x = 5 |
| dummy.ts:2:16:2:16 | [Literal] 5 | semmle.label | [Literal] 5 |
+| dummy.ts:4:1:4:24 | [ExportDeclaration] export ... /ab+c/; | semmle.label | [ExportDeclaration] export ... /ab+c/; |
+| dummy.ts:4:1:4:24 | [ExportDeclaration] export ... /ab+c/; | semmle.order | 13 |
+| dummy.ts:4:8:4:24 | [DeclStmt] let reg = ... | semmle.label | [DeclStmt] let reg = ... |
+| dummy.ts:4:12:4:14 | [VarDecl] reg | semmle.label | [VarDecl] reg |
+| dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | semmle.label | [VariableDeclarator] reg = /ab+c/ |
+| dummy.ts:4:18:4:23 | [RegExpLiteral] /ab+c/ | semmle.label | [RegExpLiteral] /ab+c/ |
+| dummy.ts:4:19:4:19 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | semmle.label | [RegExpSequence] ab+c |
+| dummy.ts:4:20:4:20 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
+| dummy.ts:4:20:4:21 | [RegExpPlus] b+ | semmle.label | [RegExpPlus] b+ |
+| dummy.ts:4:22:4:22 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
@@ -85,7 +96,7 @@ nodes
| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) |
| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | semmle.label | [DeclStmt] let foo = ... |
-| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | semmle.order | 13 |
+| middle-rest.ts:1:1:1:40 | [DeclStmt] let foo = ... | semmle.order | 14 |
| middle-rest.ts:1:5:1:7 | [VarDecl] foo | semmle.label | [VarDecl] foo |
| middle-rest.ts:1:5:1:39 | [VariableDeclarator] foo: [b ... number] | semmle.label | [VariableDeclarator] foo: [b ... number] |
| middle-rest.ts:1:10:1:39 | [TupleTypeExpr] [boolea ... number] | semmle.label | [TupleTypeExpr] [boolea ... number] |
@@ -97,55 +108,55 @@ nodes
| middle-rest.ts:3:1:3:3 | [VarRef] foo | semmle.label | [VarRef] foo |
| middle-rest.ts:3:1:3:26 | [AssignExpr] foo = [ ... ", 123] | semmle.label | [AssignExpr] foo = [ ... ", 123] |
| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | semmle.label | [ExprStmt] foo = [ ... , 123]; |
-| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | semmle.order | 14 |
+| middle-rest.ts:3:1:3:27 | [ExprStmt] foo = [ ... , 123]; | semmle.order | 15 |
| middle-rest.ts:3:7:3:26 | [ArrayExpr] [true, "hello", 123] | semmle.label | [ArrayExpr] [true, "hello", 123] |
| middle-rest.ts:3:8:3:11 | [Literal] true | semmle.label | [Literal] true |
| middle-rest.ts:3:14:3:20 | [Literal] "hello" | semmle.label | [Literal] "hello" |
| middle-rest.ts:3:23:3:25 | [Literal] 123 | semmle.label | [Literal] 123 |
| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 15 |
+| tst.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 16 |
| tst.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| tst.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| tst.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.label | [DeclStmt] var numVar = ... |
-| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 16 |
+| tst.ts:3:1:3:19 | [DeclStmt] var numVar = ... | semmle.order | 17 |
| tst.ts:3:5:3:10 | [VarDecl] numVar | semmle.label | [VarDecl] numVar |
| tst.ts:3:5:3:18 | [VariableDeclarator] numVar: number | semmle.label | [VariableDeclarator] numVar: number |
| tst.ts:3:13:3:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.label | [DeclStmt] var num1 = ... |
-| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 17 |
+| tst.ts:5:1:5:18 | [DeclStmt] var num1 = ... | semmle.order | 18 |
| tst.ts:5:5:5:8 | [VarDecl] num1 | semmle.label | [VarDecl] num1 |
| tst.ts:5:5:5:17 | [VariableDeclarator] num1 = numVar | semmle.label | [VariableDeclarator] num1 = numVar |
| tst.ts:5:12:5:17 | [VarRef] numVar | semmle.label | [VarRef] numVar |
| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.label | [DeclStmt] var num2 = ... |
-| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 18 |
+| tst.ts:6:1:6:13 | [DeclStmt] var num2 = ... | semmle.order | 19 |
| tst.ts:6:5:6:8 | [VarDecl] num2 | semmle.label | [VarDecl] num2 |
| tst.ts:6:5:6:12 | [VariableDeclarator] num2 = 5 | semmle.label | [VariableDeclarator] num2 = 5 |
| tst.ts:6:12:6:12 | [Literal] 5 | semmle.label | [Literal] 5 |
| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.label | [DeclStmt] var num3 = ... |
-| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 19 |
+| tst.ts:7:1:7:23 | [DeclStmt] var num3 = ... | semmle.order | 20 |
| tst.ts:7:5:7:8 | [VarDecl] num3 | semmle.label | [VarDecl] num3 |
| tst.ts:7:5:7:22 | [VariableDeclarator] num3 = num1 + num2 | semmle.label | [VariableDeclarator] num3 = num1 + num2 |
| tst.ts:7:12:7:15 | [VarRef] num1 | semmle.label | [VarRef] num1 |
| tst.ts:7:12:7:22 | [BinaryExpr] num1 + num2 | semmle.label | [BinaryExpr] num1 + num2 |
| tst.ts:7:19:7:22 | [VarRef] num2 | semmle.label | [VarRef] num2 |
| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.label | [DeclStmt] var strVar = ... |
-| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 20 |
+| tst.ts:9:1:9:19 | [DeclStmt] var strVar = ... | semmle.order | 21 |
| tst.ts:9:5:9:10 | [VarDecl] strVar | semmle.label | [VarDecl] strVar |
| tst.ts:9:5:9:18 | [VariableDeclarator] strVar: string | semmle.label | [VariableDeclarator] strVar: string |
| tst.ts:9:13:9:18 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.label | [DeclStmt] var hello = ... |
-| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 21 |
+| tst.ts:10:1:10:20 | [DeclStmt] var hello = ... | semmle.order | 22 |
| tst.ts:10:5:10:9 | [VarDecl] hello | semmle.label | [VarDecl] hello |
| tst.ts:10:5:10:19 | [VariableDeclarator] hello = "hello" | semmle.label | [VariableDeclarator] hello = "hello" |
| tst.ts:10:13:10:19 | [Literal] "hello" | semmle.label | [Literal] "hello" |
| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.label | [DeclStmt] var world = ... |
-| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 22 |
+| tst.ts:11:1:11:20 | [DeclStmt] var world = ... | semmle.order | 23 |
| tst.ts:11:5:11:9 | [VarDecl] world | semmle.label | [VarDecl] world |
| tst.ts:11:5:11:19 | [VariableDeclarator] world = "world" | semmle.label | [VariableDeclarator] world = "world" |
| tst.ts:11:13:11:19 | [Literal] "world" | semmle.label | [Literal] "world" |
| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.label | [DeclStmt] var msg = ... |
-| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 23 |
+| tst.ts:12:1:12:30 | [DeclStmt] var msg = ... | semmle.order | 24 |
| tst.ts:12:5:12:7 | [VarDecl] msg | semmle.label | [VarDecl] msg |
| tst.ts:12:5:12:29 | [VariableDeclarator] msg = h ... + world | semmle.label | [VariableDeclarator] msg = h ... + world |
| tst.ts:12:11:12:15 | [VarRef] hello | semmle.label | [VarRef] hello |
@@ -154,7 +165,7 @@ nodes
| tst.ts:12:19:12:21 | [Literal] " " | semmle.label | [Literal] " " |
| tst.ts:12:25:12:29 | [VarRef] world | semmle.label | [VarRef] world |
| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } |
-| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 24 |
+| tst.ts:14:1:14:63 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 25 |
| tst.ts:14:10:14:15 | [VarDecl] concat | semmle.label | [VarDecl] concat |
| tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
| tst.ts:14:20:14:25 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -167,7 +178,7 @@ nodes
| tst.ts:14:56:14:60 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y |
| tst.ts:14:60:14:60 | [VarRef] y | semmle.label | [VarRef] y |
| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } |
-| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 25 |
+| tst.ts:16:1:16:60 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 26 |
| tst.ts:16:10:16:12 | [VarDecl] add | semmle.label | [VarDecl] add |
| tst.ts:16:14:16:14 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
| tst.ts:16:17:16:22 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
@@ -180,7 +191,7 @@ nodes
| tst.ts:16:53:16:57 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y |
| tst.ts:16:57:16:57 | [VarRef] y | semmle.label | [VarRef] y |
| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } |
-| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 26 |
+| tst.ts:18:1:18:40 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 27 |
| tst.ts:18:10:18:16 | [VarDecl] untyped | semmle.label | [VarDecl] untyped |
| tst.ts:18:18:18:18 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
| tst.ts:18:21:18:21 | [SimpleParameter] y | semmle.label | [SimpleParameter] y |
@@ -190,7 +201,7 @@ nodes
| tst.ts:18:33:18:37 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y |
| tst.ts:18:37:18:37 | [VarRef] y | semmle.label | [VarRef] y |
| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.label | [FunctionDeclStmt] functio ... + y; } |
-| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 27 |
+| tst.ts:20:1:20:53 | [FunctionDeclStmt] functio ... + y; } | semmle.order | 28 |
| tst.ts:20:10:20:21 | [VarDecl] partialTyped | semmle.label | [VarDecl] partialTyped |
| tst.ts:20:23:20:23 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
| tst.ts:20:26:20:26 | [SimpleParameter] y | semmle.label | [SimpleParameter] y |
@@ -201,7 +212,7 @@ nodes
| tst.ts:20:46:20:50 | [BinaryExpr] x + y | semmle.label | [BinaryExpr] x + y |
| tst.ts:20:50:20:50 | [VarRef] y | semmle.label | [VarRef] y |
| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.label | [ForOfStmt] for (le ... 2]) {} |
-| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 28 |
+| tst.ts:22:1:22:34 | [ForOfStmt] for (le ... 2]) {} | semmle.order | 29 |
| tst.ts:22:6:22:20 | [DeclStmt] let numFromLoop = ... | semmle.label | [DeclStmt] let numFromLoop = ... |
| tst.ts:22:10:22:20 | [VarDecl] numFromLoop | semmle.label | [VarDecl] numFromLoop |
| tst.ts:22:10:22:20 | [VariableDeclarator] numFromLoop | semmle.label | [VariableDeclarator] numFromLoop |
@@ -210,54 +221,54 @@ nodes
| tst.ts:22:29:22:29 | [Literal] 2 | semmle.label | [Literal] 2 |
| tst.ts:22:33:22:34 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.label | [DeclStmt] let array = ... |
-| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 29 |
+| tst.ts:24:1:24:20 | [DeclStmt] let array = ... | semmle.order | 30 |
| tst.ts:24:5:24:9 | [VarDecl] array | semmle.label | [VarDecl] array |
| tst.ts:24:5:24:19 | [VariableDeclarator] array: number[] | semmle.label | [VariableDeclarator] array: number[] |
| tst.ts:24:12:24:17 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:24:12:24:19 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] |
| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.label | [DeclStmt] let voidType = ... |
-| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 30 |
+| tst.ts:26:1:26:25 | [DeclStmt] let voidType = ... | semmle.order | 31 |
| tst.ts:26:5:26:12 | [VarDecl] voidType | semmle.label | [VarDecl] voidType |
| tst.ts:26:5:26:24 | [VariableDeclarator] voidType: () => void | semmle.label | [VariableDeclarator] voidType: () => void |
| tst.ts:26:15:26:24 | [FunctionExpr] () => void | semmle.label | [FunctionExpr] () => void |
| tst.ts:26:15:26:24 | [FunctionTypeExpr] () => void | semmle.label | [FunctionTypeExpr] () => void |
| tst.ts:26:21:26:24 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.label | [DeclStmt] let undefinedType = ... |
-| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 31 |
+| tst.ts:27:1:27:29 | [DeclStmt] let undefinedType = ... | semmle.order | 32 |
| tst.ts:27:5:27:17 | [VarDecl] undefinedType | semmle.label | [VarDecl] undefinedType |
| tst.ts:27:5:27:28 | [VariableDeclarator] undefin ... defined | semmle.label | [VariableDeclarator] undefin ... defined |
| tst.ts:27:20:27:28 | [KeywordTypeExpr] undefined | semmle.label | [KeywordTypeExpr] undefined |
| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.label | [DeclStmt] let nullType = ... |
-| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 32 |
+| tst.ts:28:1:28:26 | [DeclStmt] let nullType = ... | semmle.order | 33 |
| tst.ts:28:5:28:12 | [VarDecl] nullType | semmle.label | [VarDecl] nullType |
| tst.ts:28:5:28:25 | [VariableDeclarator] nullTyp ... = null | semmle.label | [VariableDeclarator] nullTyp ... = null |
| tst.ts:28:15:28:18 | [KeywordTypeExpr] null | semmle.label | [KeywordTypeExpr] null |
| tst.ts:28:22:28:25 | [Literal] null | semmle.label | [Literal] null |
| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.label | [DeclStmt] let neverType = ... |
-| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 33 |
+| tst.ts:29:1:29:27 | [DeclStmt] let neverType = ... | semmle.order | 34 |
| tst.ts:29:5:29:13 | [VarDecl] neverType | semmle.label | [VarDecl] neverType |
| tst.ts:29:5:29:26 | [VariableDeclarator] neverTy ... > never | semmle.label | [VariableDeclarator] neverTy ... > never |
| tst.ts:29:16:29:26 | [FunctionExpr] () => never | semmle.label | [FunctionExpr] () => never |
| tst.ts:29:16:29:26 | [FunctionTypeExpr] () => never | semmle.label | [FunctionTypeExpr] () => never |
| tst.ts:29:22:29:26 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never |
| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.label | [DeclStmt] let symbolType = ... |
-| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 34 |
+| tst.ts:30:1:30:23 | [DeclStmt] let symbolType = ... | semmle.order | 35 |
| tst.ts:30:5:30:14 | [VarDecl] symbolType | semmle.label | [VarDecl] symbolType |
| tst.ts:30:5:30:22 | [VariableDeclarator] symbolType: symbol | semmle.label | [VariableDeclarator] symbolType: symbol |
| tst.ts:30:17:30:22 | [KeywordTypeExpr] symbol | semmle.label | [KeywordTypeExpr] symbol |
| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.label | [DeclStmt] const uniqueSymbolType = ... |
-| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 35 |
+| tst.ts:31:1:31:45 | [DeclStmt] const uniqueSymbolType = ... | semmle.order | 36 |
| tst.ts:31:7:31:22 | [VarDecl] uniqueSymbolType | semmle.label | [VarDecl] uniqueSymbolType |
| tst.ts:31:7:31:44 | [VariableDeclarator] uniqueS ... = null | semmle.label | [VariableDeclarator] uniqueS ... = null |
| tst.ts:31:25:31:37 | [KeywordTypeExpr] unique symbol | semmle.label | [KeywordTypeExpr] unique symbol |
| tst.ts:31:41:31:44 | [Literal] null | semmle.label | [Literal] null |
| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.label | [DeclStmt] let objectType = ... |
-| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 36 |
+| tst.ts:32:1:32:23 | [DeclStmt] let objectType = ... | semmle.order | 37 |
| tst.ts:32:5:32:14 | [VarDecl] objectType | semmle.label | [VarDecl] objectType |
| tst.ts:32:5:32:22 | [VariableDeclarator] objectType: object | semmle.label | [VariableDeclarator] objectType: object |
| tst.ts:32:17:32:22 | [KeywordTypeExpr] object | semmle.label | [KeywordTypeExpr] object |
| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.label | [DeclStmt] let intersection = ... |
-| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 37 |
+| tst.ts:33:1:33:39 | [DeclStmt] let intersection = ... | semmle.order | 38 |
| tst.ts:33:5:33:16 | [VarDecl] intersection | semmle.label | [VarDecl] intersection |
| tst.ts:33:5:33:38 | [VariableDeclarator] interse ... string} | semmle.label | [VariableDeclarator] interse ... string} |
| tst.ts:33:19:33:24 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -267,14 +278,14 @@ nodes
| tst.ts:33:29:33:37 | [FieldDeclaration] x: string | semmle.label | [FieldDeclaration] x: string |
| tst.ts:33:32:33:37 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.label | [DeclStmt] let tuple = ... |
-| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 38 |
+| tst.ts:34:1:34:28 | [DeclStmt] let tuple = ... | semmle.order | 39 |
| tst.ts:34:5:34:9 | [VarDecl] tuple | semmle.label | [VarDecl] tuple |
| tst.ts:34:5:34:27 | [VariableDeclarator] tuple: ... string] | semmle.label | [VariableDeclarator] tuple: ... string] |
| tst.ts:34:12:34:27 | [TupleTypeExpr] [number, string] | semmle.label | [TupleTypeExpr] [number, string] |
| tst.ts:34:13:34:18 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:34:21:34:26 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.label | [DeclStmt] let tupleWithOptionalElement = ... |
-| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 39 |
+| tst.ts:36:1:36:56 | [DeclStmt] let tupleWithOptionalElement = ... | semmle.order | 40 |
| tst.ts:36:5:36:28 | [VarDecl] tupleWithOptionalElement | semmle.label | [VarDecl] tupleWithOptionalElement |
| tst.ts:36:5:36:55 | [VariableDeclarator] tupleWi ... umber?] | semmle.label | [VariableDeclarator] tupleWi ... umber?] |
| tst.ts:36:31:36:55 | [TupleTypeExpr] [number ... umber?] | semmle.label | [TupleTypeExpr] [number ... umber?] |
@@ -283,12 +294,12 @@ nodes
| tst.ts:36:48:36:53 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:36:48:36:54 | [OptionalTypeExpr] number? | semmle.label | [OptionalTypeExpr] number? |
| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.label | [DeclStmt] let emptyTuple = ... |
-| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 40 |
+| tst.ts:37:1:37:19 | [DeclStmt] let emptyTuple = ... | semmle.order | 41 |
| tst.ts:37:5:37:14 | [VarDecl] emptyTuple | semmle.label | [VarDecl] emptyTuple |
| tst.ts:37:5:37:18 | [VariableDeclarator] emptyTuple: [] | semmle.label | [VariableDeclarator] emptyTuple: [] |
| tst.ts:37:17:37:18 | [TupleTypeExpr] [] | semmle.label | [TupleTypeExpr] [] |
| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.label | [DeclStmt] let tupleWithRestElement = ... |
-| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 41 |
+| tst.ts:38:1:38:48 | [DeclStmt] let tupleWithRestElement = ... | semmle.order | 42 |
| tst.ts:38:5:38:24 | [VarDecl] tupleWithRestElement | semmle.label | [VarDecl] tupleWithRestElement |
| tst.ts:38:5:38:47 | [VariableDeclarator] tupleWi ... ring[]] | semmle.label | [VariableDeclarator] tupleWi ... ring[]] |
| tst.ts:38:27:38:47 | [TupleTypeExpr] [number ... ring[]] | semmle.label | [TupleTypeExpr] [number ... ring[]] |
@@ -297,7 +308,7 @@ nodes
| tst.ts:38:39:38:44 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
| tst.ts:38:39:38:46 | [ArrayTypeExpr] string[] | semmle.label | [ArrayTypeExpr] string[] |
| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.label | [DeclStmt] let tupleWithOptionalAndRestElements = ... |
-| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 42 |
+| tst.ts:39:1:39:69 | [DeclStmt] let tupleWithOptionalAndRestElements = ... | semmle.order | 43 |
| tst.ts:39:5:39:36 | [VarDecl] tupleWithOptionalAndRestElements | semmle.label | [VarDecl] tupleWithOptionalAndRestElements |
| tst.ts:39:5:39:68 | [VariableDeclarator] tupleWi ... mber[]] | semmle.label | [VariableDeclarator] tupleWi ... mber[]] |
| tst.ts:39:39:39:68 | [TupleTypeExpr] [number ... mber[]] | semmle.label | [TupleTypeExpr] [number ... mber[]] |
@@ -308,12 +319,12 @@ nodes
| tst.ts:39:60:39:65 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:39:60:39:67 | [ArrayTypeExpr] number[] | semmle.label | [ArrayTypeExpr] number[] |
| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.label | [DeclStmt] let unknownType = ... |
-| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 43 |
+| tst.ts:40:1:40:25 | [DeclStmt] let unknownType = ... | semmle.order | 44 |
| tst.ts:40:5:40:15 | [VarDecl] unknownType | semmle.label | [VarDecl] unknownType |
| tst.ts:40:5:40:24 | [VariableDeclarator] unknownType: unknown | semmle.label | [VariableDeclarator] unknownType: unknown |
| tst.ts:40:18:40:24 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown |
| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.label | [DeclStmt] let constArrayLiteral = ... |
-| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 44 |
+| tst.ts:42:1:42:40 | [DeclStmt] let constArrayLiteral = ... | semmle.order | 45 |
| tst.ts:42:5:42:21 | [VarDecl] constArrayLiteral | semmle.label | [VarDecl] constArrayLiteral |
| tst.ts:42:5:42:39 | [VariableDeclarator] constAr ... s const | semmle.label | [VariableDeclarator] constAr ... s const |
| tst.ts:42:25:42:30 | [ArrayExpr] [1, 2] | semmle.label | [ArrayExpr] [1, 2] |
@@ -322,7 +333,7 @@ nodes
| tst.ts:42:29:42:29 | [Literal] 2 | semmle.label | [Literal] 2 |
| tst.ts:42:35:42:39 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const |
| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.label | [DeclStmt] let constObjectLiteral = ... |
-| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 45 |
+| tst.ts:43:1:43:49 | [DeclStmt] let constObjectLiteral = ... | semmle.order | 46 |
| tst.ts:43:5:43:22 | [VarDecl] constObjectLiteral | semmle.label | [VarDecl] constObjectLiteral |
| tst.ts:43:5:43:48 | [VariableDeclarator] constOb ... s const | semmle.label | [VariableDeclarator] constOb ... s const |
| tst.ts:43:26:43:39 | [ObjectExpr] {foo: ...} | semmle.label | [ObjectExpr] {foo: ...} |
@@ -332,7 +343,7 @@ nodes
| tst.ts:43:33:43:37 | [Literal] "foo" | semmle.label | [Literal] "foo" |
| tst.ts:43:44:43:48 | [KeywordTypeExpr] const | semmle.label | [KeywordTypeExpr] const |
| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.label | [TryStmt] try { } ... ; } } |
-| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 46 |
+| tst.ts:46:1:51:1 | [TryStmt] try { } ... ; } } | semmle.order | 47 |
| tst.ts:46:5:46:7 | [BlockStmt] { } | semmle.label | [BlockStmt] { } |
| tst.ts:47:1:51:1 | [CatchClause] catch ( ... ; } } | semmle.label | [CatchClause] catch ( ... ; } } |
| tst.ts:47:8:47:8 | [SimpleParameter] e | semmle.label | [SimpleParameter] e |
@@ -349,21 +360,21 @@ nodes
| tst.ts:49:15:49:20 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
| tst.ts:49:24:49:24 | [VarRef] e | semmle.label | [VarRef] e |
| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } |
-| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 47 |
+| tst.ts:54:1:56:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 48 |
| tst.ts:54:11:54:26 | [Identifier] NonAbstractDummy | semmle.label | [Identifier] NonAbstractDummy |
| tst.ts:55:3:55:9 | [Label] getArea | semmle.label | [Label] getArea |
| tst.ts:55:3:55:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; |
| tst.ts:55:3:55:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; |
| tst.ts:55:14:55:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } |
-| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 48 |
+| tst.ts:58:1:60:1 | [InterfaceDeclaration,TypeDefinition] interfa ... mber; } | semmle.order | 49 |
| tst.ts:58:11:58:17 | [Identifier] HasArea | semmle.label | [Identifier] HasArea |
| tst.ts:59:3:59:9 | [Label] getArea | semmle.label | [Label] getArea |
| tst.ts:59:3:59:20 | [FunctionExpr] getArea(): number; | semmle.label | [FunctionExpr] getArea(): number; |
| tst.ts:59:3:59:20 | [MethodSignature] getArea(): number; | semmle.label | [MethodSignature] getArea(): number; |
| tst.ts:59:14:59:19 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.label | [DeclStmt] let Ctor = ... |
-| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.order | 49 |
+| tst.ts:63:1:63:45 | [DeclStmt] let Ctor = ... | semmle.order | 50 |
| tst.ts:63:5:63:8 | [VarDecl] Ctor | semmle.label | [VarDecl] Ctor |
| tst.ts:63:5:63:44 | [VariableDeclarator] Ctor: a ... = Shape | semmle.label | [VariableDeclarator] Ctor: a ... = Shape |
| tst.ts:63:11:63:36 | [FunctionExpr] abstrac ... HasArea | semmle.label | [FunctionExpr] abstrac ... HasArea |
@@ -371,7 +382,7 @@ nodes
| tst.ts:63:30:63:36 | [LocalTypeAccess] HasArea | semmle.label | [LocalTypeAccess] HasArea |
| tst.ts:63:40:63:44 | [VarRef] Shape | semmle.label | [VarRef] Shape |
| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; |
-| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 50 |
+| tst.ts:65:1:65:54 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 51 |
| tst.ts:65:6:65:12 | [Identifier] MyUnion | semmle.label | [Identifier] MyUnion |
| tst.ts:65:16:65:30 | [InterfaceTypeExpr] {myUnion: true} | semmle.label | [InterfaceTypeExpr] {myUnion: true} |
| tst.ts:65:16:65:53 | [UnionTypeExpr] {myUnio ... : true} | semmle.label | [UnionTypeExpr] {myUnio ... : true} |
@@ -383,7 +394,7 @@ nodes
| tst.ts:65:35:65:52 | [FieldDeclaration] stillMyUnion: true | semmle.label | [FieldDeclaration] stillMyUnion: true |
| tst.ts:65:49:65:52 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true |
| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.label | [DeclStmt] let union1 = ... |
-| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.order | 51 |
+| tst.ts:66:1:66:38 | [DeclStmt] let union1 = ... | semmle.order | 52 |
| tst.ts:66:5:66:10 | [VarDecl] union1 | semmle.label | [VarDecl] union1 |
| tst.ts:66:5:66:37 | [VariableDeclarator] union1: ... : true} | semmle.label | [VariableDeclarator] union1: ... : true} |
| tst.ts:66:13:66:19 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion |
@@ -392,7 +403,7 @@ nodes
| tst.ts:66:24:66:36 | [Property] myUnion: true | semmle.label | [Property] myUnion: true |
| tst.ts:66:33:66:36 | [Literal] true | semmle.label | [Literal] true |
| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type My ... true}; |
-| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 52 |
+| tst.ts:68:1:68:49 | [TypeAliasDeclaration,TypeDefinition] type My ... true}; | semmle.order | 53 |
| tst.ts:68:6:68:13 | [Identifier] MyUnion2 | semmle.label | [Identifier] MyUnion2 |
| tst.ts:68:17:68:23 | [LocalTypeAccess] MyUnion | semmle.label | [LocalTypeAccess] MyUnion |
| tst.ts:68:17:68:48 | [UnionTypeExpr] MyUnion ... : true} | semmle.label | [UnionTypeExpr] MyUnion ... : true} |
@@ -401,7 +412,7 @@ nodes
| tst.ts:68:28:68:47 | [FieldDeclaration] yetAnotherType: true | semmle.label | [FieldDeclaration] yetAnotherType: true |
| tst.ts:68:44:68:47 | [LiteralTypeExpr] true | semmle.label | [LiteralTypeExpr] true |
| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.label | [DeclStmt] let union2 = ... |
-| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.order | 53 |
+| tst.ts:69:1:69:46 | [DeclStmt] let union2 = ... | semmle.order | 54 |
| tst.ts:69:5:69:10 | [VarDecl] union2 | semmle.label | [VarDecl] union2 |
| tst.ts:69:5:69:45 | [VariableDeclarator] union2: ... : true} | semmle.label | [VariableDeclarator] union2: ... : true} |
| tst.ts:69:13:69:20 | [LocalTypeAccess] MyUnion2 | semmle.label | [LocalTypeAccess] MyUnion2 |
@@ -410,16 +421,16 @@ nodes
| tst.ts:69:25:69:44 | [Property] yetAnotherType: true | semmle.label | [Property] yetAnotherType: true |
| tst.ts:69:41:69:44 | [Literal] true | semmle.label | [Literal] true |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; |
-| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 54 |
+| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 55 |
| type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B |
| type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... |
-| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 55 |
+| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 56 |
| type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b |
| type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B |
| type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; |
-| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 56 |
+| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 57 |
| type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray |
| type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T |
| type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T |
@@ -431,14 +442,14 @@ nodes
| type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... |
-| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 57 |
+| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 58 |
| type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> |
| type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray |
| type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; |
-| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 58 |
+| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 59 |
| type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json |
| type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] |
| type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -454,12 +465,12 @@ nodes
| type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... |
-| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 59 |
+| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 60 |
| type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json |
| type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json |
| type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; |
-| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 60 |
+| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 61 |
| type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode |
| type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] |
| type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -475,7 +486,7 @@ nodes
| type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
| type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... |
-| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 61 |
+| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 62 |
| type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode |
| type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] |
| type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
@@ -500,12 +511,12 @@ nodes
| type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" |
| type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 62 |
+| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 63 |
| type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} |
-| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 63 |
+| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 64 |
| type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} |
| type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
@@ -513,36 +524,36 @@ nodes
| type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
| type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... |
-| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 64 |
+| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 65 |
| type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj |
| type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C |
| type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} |
-| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 65 |
+| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 66 |
| type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} |
| type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... |
-| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 66 |
+| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 67 |
| type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj |
| type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E |
| type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} |
-| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 67 |
+| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 68 |
| type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} |
| type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N |
| type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... |
-| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 68 |
+| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 69 |
| type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj |
| type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N |
| type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 69 |
+| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 70 |
| type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } |
-| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 70 |
+| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 71 |
| type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I |
| type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S |
| type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S |
@@ -550,14 +561,14 @@ nodes
| type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; |
| type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... |
-| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 71 |
+| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 72 |
| type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i |
| type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I |
| type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I |
| type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I |
| type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } |
-| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 72 |
+| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 73 |
| type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
| type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} |
@@ -569,14 +580,14 @@ nodes
| type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T |
| type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... |
-| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 73 |
+| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 74 |
| type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C |
| type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C |
| type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C |
| type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } |
-| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 74 |
+| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 75 |
| type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color |
| type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red |
| type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red |
@@ -585,29 +596,29 @@ nodes
| type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue |
| type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue |
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... |
-| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 75 |
+| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 76 |
| type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color |
| type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color |
| type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color |
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } |
-| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 76 |
+| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 77 |
| type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember |
| type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member |
| type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member |
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... |
-| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 77 |
+| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 78 |
| type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e |
| type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember |
| type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember |
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; |
-| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 78 |
+| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 79 |
| type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias |
| type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T |
| type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
| type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] |
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... |
-| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 79 |
+| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 80 |
| type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray |
| type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> |
| type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias |
@@ -716,6 +727,24 @@ edges
| dummy.ts:2:12:2:16 | [VariableDeclarator] x = 5 | dummy.ts:2:12:2:12 | [VarDecl] x | semmle.order | 1 |
| dummy.ts:2:12:2:16 | [VariableDeclarator] x = 5 | dummy.ts:2:16:2:16 | [Literal] 5 | semmle.label | 2 |
| dummy.ts:2:12:2:16 | [VariableDeclarator] x = 5 | dummy.ts:2:16:2:16 | [Literal] 5 | semmle.order | 2 |
+| dummy.ts:4:1:4:24 | [ExportDeclaration] export ... /ab+c/; | dummy.ts:4:8:4:24 | [DeclStmt] let reg = ... | semmle.label | 1 |
+| dummy.ts:4:1:4:24 | [ExportDeclaration] export ... /ab+c/; | dummy.ts:4:8:4:24 | [DeclStmt] let reg = ... | semmle.order | 1 |
+| dummy.ts:4:8:4:24 | [DeclStmt] let reg = ... | dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | semmle.label | 1 |
+| dummy.ts:4:8:4:24 | [DeclStmt] let reg = ... | dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | semmle.order | 1 |
+| dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | dummy.ts:4:12:4:14 | [VarDecl] reg | semmle.label | 1 |
+| dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | dummy.ts:4:12:4:14 | [VarDecl] reg | semmle.order | 1 |
+| dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | dummy.ts:4:18:4:23 | [RegExpLiteral] /ab+c/ | semmle.label | 2 |
+| dummy.ts:4:12:4:23 | [VariableDeclarator] reg = /ab+c/ | dummy.ts:4:18:4:23 | [RegExpLiteral] /ab+c/ | semmle.order | 2 |
+| dummy.ts:4:18:4:23 | [RegExpLiteral] /ab+c/ | dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | semmle.label | 0 |
+| dummy.ts:4:18:4:23 | [RegExpLiteral] /ab+c/ | dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | semmle.order | 0 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:19:4:19 | [RegExpNormalConstant] a | semmle.label | 0 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:19:4:19 | [RegExpNormalConstant] a | semmle.order | 0 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:20:4:21 | [RegExpPlus] b+ | semmle.label | 1 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:20:4:21 | [RegExpPlus] b+ | semmle.order | 1 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:22:4:22 | [RegExpNormalConstant] c | semmle.label | 2 |
+| dummy.ts:4:19:4:22 | [RegExpSequence] ab+c | dummy.ts:4:22:4:22 | [RegExpNormalConstant] c | semmle.order | 2 |
+| dummy.ts:4:20:4:21 | [RegExpPlus] b+ | dummy.ts:4:20:4:20 | [RegExpNormalConstant] b | semmle.label | 0 |
+| dummy.ts:4:20:4:21 | [RegExpPlus] b+ | dummy.ts:4:20:4:20 | [RegExpNormalConstant] b | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | tst.ts:14:28:14:28 | [SimpleParameter] y | semmle.label | 1 |
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
index c9cad8a1443..7c8159a9b10 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
@@ -15,6 +15,8 @@ getExprType
| boolean-type.ts:15:5:15:12 | boolean6 | boolean |
| dummy.ts:2:12:2:12 | x | number |
| dummy.ts:2:16:2:16 | 5 | 5 |
+| dummy.ts:4:12:4:14 | reg | RegExp |
+| dummy.ts:4:18:4:23 | /ab+c/ | RegExp |
| middle-rest.ts:1:5:1:7 | foo | [boolean, ...string[], number] |
| middle-rest.ts:3:1:3:3 | foo | [boolean, ...string[], number] |
| middle-rest.ts:3:1:3:26 | foo = [ ... ", 123] | [true, string, number] |
From 504c34ed2c1493b0f7b413e710e8545d8ebfd21f Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Mon, 10 May 2021 14:51:13 +0200
Subject: [PATCH 098/168] use shouldPrint to filter out regular expressions
from other files
---
javascript/ql/src/semmle/javascript/PrintAst.qll | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/javascript/ql/src/semmle/javascript/PrintAst.qll b/javascript/ql/src/semmle/javascript/PrintAst.qll
index 99f06354d74..029cfd536fc 100644
--- a/javascript/ql/src/semmle/javascript/PrintAst.qll
+++ b/javascript/ql/src/semmle/javascript/PrintAst.qll
@@ -74,7 +74,11 @@ private newtype TPrintAstNode =
THTMLAttributeNode(HTML::Attribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
THTMLScript(Script script) { shouldPrint(script, _) and not isNotNeeded(script) } or
THTMLCodeInAttr(CodeInAttribute attr) { shouldPrint(attr, _) and not isNotNeeded(attr) } or
- TRegExpTermNode(RegExpTerm term) { term.isUsedAsRegExp() }
+ TRegExpTermNode(RegExpTerm term) {
+ shouldPrint(term, _) and
+ term.isUsedAsRegExp() and
+ any(RegExpLiteral lit).getRoot() = term.getRootTerm()
+ }
/**
* A node in the output tree.
From 78370cf63fa0bf528c3f566654c73bdf25547f1f Mon Sep 17 00:00:00 2001
From: yoff
Date: Mon, 10 May 2021 14:53:40 +0200
Subject: [PATCH 099/168] Update
python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
---
python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
index 05ea4f62630..4f3457e0a99 100644
--- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll
@@ -58,7 +58,7 @@ private module Re {
* This class will identify that `re.compile` compiles `input` and afterwards
* executes `re`'s `match`. As a result, `this` will refer to `pattern.match(s)`
* and `this.getRegexNode()` will return the node for `input` (`re.compile`'s first argument)
- *
+ *
*
* See `RegexExecutionMethods`
*
From 31ac6442e8c3161405938f8621d6c15b34439df8 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Mon, 10 May 2021 15:49:31 +0200
Subject: [PATCH 100/168] C#: Fix default parameter value generation in case of
error symbols
---
.../extractor/Semmle.Extraction.CSharp/Entities/Expression.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
index 103ea8cacda..a478047ac7b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
@@ -170,7 +170,8 @@ namespace Semmle.Extraction.CSharp.Entities
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
int childIndex, Extraction.Entities.Location location)
{
- if (!parameter.HasExplicitDefaultValue)
+ if (!parameter.HasExplicitDefaultValue ||
+ parameter.Type is IErrorTypeSymbol)
{
return null;
}
From dd86da3f242ea1186f85be6da8e424940b91fe02 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Mon, 10 May 2021 15:48:33 +0200
Subject: [PATCH 101/168] C#: Remove base class from type IDs in trap files
---
.../Entities/Types/Type.cs | 74 +-
.../SymbolExtensions.cs | 47 +-
csharp/ql/src/semmlecode.csharp.dbscheme | 2 +-
.../old.dbscheme | 2083 +++++++++++++++++
.../semmlecode.csharp.dbscheme | 2083 +++++++++++++++++
.../upgrade.properties | 2 +
6 files changed, 4233 insertions(+), 58 deletions(-)
create mode 100644 csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/old.dbscheme
create mode 100644 csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/semmlecode.csharp.dbscheme
create mode 100644 csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/upgrade.properties
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
index e2522648678..67936f9a913 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs
@@ -81,22 +81,45 @@ namespace Semmle.Extraction.CSharp.Entities
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
trapFile.WriteLine("\")");
+ var baseTypes = GetBaseTypeDeclarations();
+
// Visit base types
- var baseTypes = new List();
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
{
- var baseKey = Create(Context, @base);
- trapFile.extend(this, baseKey.TypeRef);
- if (Symbol.TypeKind != TypeKind.Struct)
- baseTypes.Add(baseKey);
+ var bts = GetBaseTypeDeclarations(baseTypes, @base);
+
+ Context.PopulateLater(() =>
+ {
+ var baseKey = Create(Context, @base);
+ trapFile.extend(this, baseKey.TypeRef);
+
+ if (Symbol.TypeKind != TypeKind.Struct)
+ {
+ foreach (var bt in bts)
+ {
+ TypeMention.Create(Context, bt.Type, this, baseKey);
+ }
+ }
+ });
}
+ // Visit implemented interfaces
if (!(base.Symbol is IArrayTypeSymbol))
{
- foreach (var t in base.Symbol.Interfaces.Select(i => Create(Context, i)))
+ foreach (var i in base.Symbol.Interfaces)
{
- trapFile.implement(this, t.TypeRef);
- baseTypes.Add(t);
+ var bts = GetBaseTypeDeclarations(baseTypes, i);
+
+ Context.PopulateLater(() =>
+ {
+ var interfaceKey = Create(Context, i);
+ trapFile.implement(this, interfaceKey.TypeRef);
+
+ foreach (var bt in bts)
+ {
+ TypeMention.Create(Context, bt.Type, this, interfaceKey);
+ }
+ });
}
}
@@ -145,23 +168,30 @@ namespace Semmle.Extraction.CSharp.Entities
}
Modifier.ExtractModifiers(Context, trapFile, this, Symbol);
+ }
- if (IsSourceDeclaration && Symbol.FromSource())
+ private IEnumerable GetBaseTypeDeclarations()
+ {
+ if (!IsSourceDeclaration || !Symbol.FromSource())
{
- var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
-
- var baseLists = declSyntaxReferences.OfType().Select(c => c.BaseList);
- baseLists = baseLists.Concat(declSyntaxReferences.OfType().Select(c => c.BaseList));
- baseLists = baseLists.Concat(declSyntaxReferences.OfType().Select(c => c.BaseList));
-
- baseLists
- .Where(bl => bl is not null)
- .SelectMany(bl => bl!.Types)
- .Zip(
- baseTypes.Where(bt => bt.Symbol.SpecialType != SpecialType.System_Object),
- (s, t) => TypeMention.Create(Context, s.Type, this, t))
- .Enumerate();
+ return Enumerable.Empty();
}
+
+ var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
+
+ var baseLists = declSyntaxReferences.OfType().Select(c => c.BaseList);
+ baseLists = baseLists.Concat(declSyntaxReferences.OfType().Select(c => c.BaseList));
+ baseLists = baseLists.Concat(declSyntaxReferences.OfType().Select(c => c.BaseList));
+
+ return baseLists
+ .Where(bl => bl is not null)
+ .SelectMany(bl => bl!.Types)
+ .ToList();
+ }
+
+ private IEnumerable GetBaseTypeDeclarations(IEnumerable baseTypes, INamedTypeSymbol type)
+ {
+ return baseTypes.Where(bt => SymbolEqualityComparer.Default.Equals(Context.GetModel(bt).GetTypeInfo(bt.Type).Type, type));
}
private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSymbol invokeMethod, Action storeReturnType)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 32b90e37068..91f0d0edf20 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -121,8 +121,6 @@ namespace Semmle.Extraction.CSharp
named = named.TupleUnderlyingType;
if (IdDependsOnImpl(named.ContainingType))
return true;
- if (IdDependsOnImpl(named.GetNonObjectBaseType(cx)))
- return true;
if (IdDependsOnImpl(named.ConstructedFrom))
return true;
return named.TypeArguments.Any(IdDependsOnImpl);
@@ -160,10 +158,7 @@ namespace Semmle.Extraction.CSharp
/// The trap builder used to store the result.
/// The outer symbol being defined (to avoid recursive ids).
/// Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.
- public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
- type.BuildTypeId(cx, trapFile, symbolBeingDefined, true, constructUnderlyingTupleType);
-
- private static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
+ public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false)
{
using (cx.StackGuard)
{
@@ -171,7 +166,7 @@ namespace Semmle.Extraction.CSharp
{
case TypeKind.Array:
var array = (IArrayTypeSymbol)type;
- array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
+ array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
array.BuildArraySuffix(trapFile);
return;
case TypeKind.Class:
@@ -181,16 +176,16 @@ namespace Semmle.Extraction.CSharp
case TypeKind.Delegate:
case TypeKind.Error:
var named = (INamedTypeSymbol)type;
- named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
+ named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
return;
case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type;
- ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
+ ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
trapFile.Write('*');
return;
case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type;
- tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
+ tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
trapFile.Write('_');
trapFile.Write(tp.Name);
return;
@@ -207,7 +202,7 @@ namespace Semmle.Extraction.CSharp
}
}
- private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType = false)
+ private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false)
{
if (symbol is null)
{
@@ -232,7 +227,7 @@ namespace Semmle.Extraction.CSharp
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
trapFile.Write("__self__");
else if (symbol is ITypeSymbol type && type.IdDependsOn(cx, symbolBeingDefined))
- type.BuildTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
+ type.BuildTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
else if (symbol is INamedTypeSymbol namedType && namedType.IsTupleType && constructUnderlyingTupleType)
trapFile.WriteSubId(NamedType.CreateNamedTypeFromTupleType(cx, namedType));
else
@@ -287,7 +282,7 @@ namespace Semmle.Extraction.CSharp
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
}
- private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
+ private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
@@ -297,7 +292,7 @@ namespace Semmle.Extraction.CSharp
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
- f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
+ f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
}
);
trapFile.Write(")");
@@ -308,7 +303,7 @@ namespace Semmle.Extraction.CSharp
{
if (named.ContainingType is not null)
{
- named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
+ named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
trapFile.Write('.');
}
else if (named.ContainingNamespace is not null)
@@ -333,35 +328,17 @@ namespace Semmle.Extraction.CSharp
}
else
{
- named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
+ named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
trapFile.Write('<');
// Encode the nullability of the type arguments in the label.
// Type arguments with different nullability can result in
// a constructed type with different nullability of its members and methods,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
- ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass)
+ ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined)
);
trapFile.Write('>');
}
-
- if (addBaseClass && named.GetNonObjectBaseType(cx) is INamedTypeSymbol @base)
- {
- // We need to limit unfolding of base classes. For example, in
- //
- // ```csharp
- // class C1 { }
- // class C2 : C1> { }
- // class C3 : C1> { }
- // class C4 : C3 { }
- // ```
- //
- // when we generate the label for `C4`, the base class `C3` has itself `C1>` as
- // a base class, which in turn has `C1>` as a base class. The latter has the original
- // base class `C3` as a type argument, which would lead to infinite unfolding.
- trapFile.Write(" : ");
- @base.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass: false);
- }
}
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, EscapingTextWriter trapFile)
diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme
index 9258e9b38d8..770f844243d 100644
--- a/csharp/ql/src/semmlecode.csharp.dbscheme
+++ b/csharp/ql/src/semmlecode.csharp.dbscheme
@@ -529,7 +529,7 @@ function_pointer_return_type(
int return_type_id: @type_or_ref ref);
extend(
- unique int sub: @type ref,
+ int sub: @type ref,
int super: @type_or_ref ref);
anonymous_types(
diff --git a/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/old.dbscheme b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/old.dbscheme
new file mode 100644
index 00000000000..9258e9b38d8
--- /dev/null
+++ b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/old.dbscheme
@@ -0,0 +1,2083 @@
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+/*
+ fromSource(0) = unknown,
+ fromSource(1) = from source,
+ fromSource(2) = from library
+*/
+files(
+ unique int id: @file,
+ string name: string ref,
+ string simple: string ref,
+ string ext: string ref,
+ int fromSource: int ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref,
+ string simple: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref
+)
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ unique int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/semmlecode.csharp.dbscheme b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/semmlecode.csharp.dbscheme
new file mode 100644
index 00000000000..770f844243d
--- /dev/null
+++ b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/semmlecode.csharp.dbscheme
@@ -0,0 +1,2083 @@
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+/*
+ fromSource(0) = unknown,
+ fromSource(1) = from source,
+ fromSource(2) = from library
+*/
+files(
+ unique int id: @file,
+ string name: string ref,
+ string simple: string ref,
+ string ext: string ref,
+ int fromSource: int ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref,
+ string simple: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref
+)
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/upgrade.properties b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/upgrade.properties
new file mode 100644
index 00000000000..64b44aecc3c
--- /dev/null
+++ b/csharp/upgrades/9258e9b38d85f92cee9559f2ed21e241f0c7a29e/upgrade.properties
@@ -0,0 +1,2 @@
+description: Removed unique base class constraint
+compatibility: backwards
From d27316eb3e7227930e966d7eba441496e4281dad Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 10 May 2021 11:55:31 -0400
Subject: [PATCH 102/168] Apply suggestions from code review
Co-authored-by: Marcono1234
---
java/change-notes/2021-05-05-kryo-improvements.md | 2 +-
java/ql/src/semmle/code/java/frameworks/Kryo.qll | 2 +-
java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/change-notes/2021-05-05-kryo-improvements.md b/java/change-notes/2021-05-05-kryo-improvements.md
index f8ba79eb863..5b39d1daae0 100644
--- a/java/change-notes/2021-05-05-kryo-improvements.md
+++ b/java/change-notes/2021-05-05-kryo-improvements.md
@@ -1,3 +1,3 @@
lgtm,codescanning
* Add support for version 5 of the Kryo serialzation/deserialization framework.
-* Add support for detecting safe uses of Kryo utilizing `KryoPool.Builder. (#4992)[https://github.com/github/codeql/issues/4992]
+* Add support for detecting safe uses of Kryo utilizing `KryoPool.Builder`. [#4992](https://github.com/github/codeql/issues/4992)
diff --git a/java/ql/src/semmle/code/java/frameworks/Kryo.qll b/java/ql/src/semmle/code/java/frameworks/Kryo.qll
index 16873fc751f..317148d56b5 100644
--- a/java/ql/src/semmle/code/java/frameworks/Kryo.qll
+++ b/java/ql/src/semmle/code/java/frameworks/Kryo.qll
@@ -47,7 +47,7 @@ class KryoPoolBuilder extends RefType {
}
/**
- * A Kryo pool builder method used a fluent API call chain.
+ * A Kryo pool builder method used in a fluent API call chain.
*/
class KryoPoolBuilderMethod extends Method {
KryoPoolBuilderMethod() {
diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
index def37c0964e..a1561c0e6cd 100644
--- a/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
+++ b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll
@@ -57,7 +57,7 @@ class SafeKryo extends DataFlow2::Configuration {
}
/**
- * Holds when a funcitonal expression is used to create a `KryoPool.Builder`.
+ * Holds when a functional expression is used to create a `KryoPool.Builder`.
* Eg. `new KryoPool.Builder(() -> new Kryo())`
*/
private predicate stepKryoPoolBuilderFactoryArgToConstructor(
From 54f191cfe37e136bcc7189b2fb01f44dbb01758b Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 11 May 2021 11:23:03 +0200
Subject: [PATCH 103/168] add support for rejected promise values in API graphs
---
.../ql/src/semmle/javascript/ApiGraphs.qll | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll
index 385dc1e76d3..590142590a4 100644
--- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll
@@ -183,6 +183,11 @@ module API {
*/
Node getPromised() { result = getASuccessor(Label::promised()) }
+ /**
+ * Gets a node representing the error wrapped in the `Promise` object represented by this node.
+ */
+ Node getPromisedError() { result = getASuccessor(Label::promisedError()) }
+
/**
* Gets a string representation of the lexicographically least among all shortest access paths
* from the root to this node.
@@ -468,6 +473,9 @@ module API {
or
lbl = Label::promised() and
PromiseFlow::storeStep(rhs, pred, Promises::valueProp())
+ or
+ lbl = Label::promisedError() and
+ PromiseFlow::storeStep(rhs, pred, Promises::errorProp())
)
or
exists(DataFlow::ClassNode cls, string name |
@@ -482,6 +490,12 @@ module API {
rhs = f.getAReturn()
)
or
+ exists(DataFlow::FunctionNode f |
+ base = MkAsyncFuncResult(f) and
+ lbl = Label::promisedError() and
+ rhs = f.getExceptionalReturn()
+ )
+ or
exists(int i |
lbl = Label::parameter(i) and
argumentPassing(base, i, rhs)
@@ -559,6 +573,9 @@ module API {
or
lbl = Label::promised() and
PromiseFlow::loadStep(pred, ref, Promises::valueProp())
+ or
+ lbl = Label::promisedError() and
+ PromiseFlow::loadStep(pred, ref, Promises::errorProp())
)
or
exists(DataFlow::Node def, DataFlow::FunctionNode fn |
@@ -962,6 +979,9 @@ private module Label {
/** Gets the `promised` edge label connecting a promise to its contained value. */
string promised() { result = "promised" }
+
+ /** Gets the `promisedError` edge label connecting a promise to its rejected value. */
+ string promisedError() { result = "promisedError" }
}
private class NodeModuleSourcesNodes extends DataFlow::SourceNode::Range {
From 52991dc4a1ec07410fa2818776f756c12418f707 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 11 May 2021 11:23:51 +0200
Subject: [PATCH 104/168] rewrite the axios model to use API graphs
---
.../javascript/frameworks/ClientRequests.qll | 23 +++++++------------
1 file changed, 8 insertions(+), 15 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
index 451ad3f24d2..78f7ec92a16 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
@@ -206,19 +206,14 @@ module ClientRequest {
/**
* A model of a URL request made using the `axios` library.
*/
- class AxiosUrlRequest extends ClientRequest::Range {
+ class AxiosUrlRequest extends ClientRequest::Range, API::CallNode {
string method;
AxiosUrlRequest() {
- exists(string moduleName, DataFlow::SourceNode callee | this = callee.getACall() |
- moduleName = "axios" and
- (
- callee = DataFlow::moduleImport(moduleName) and method = "request"
- or
- callee = DataFlow::moduleMember(moduleName, method) and
- (method = httpMethodName() or method = "request")
- )
- )
+ this = API::moduleImport("axios").getACall() and method = "request"
+ or
+ this = API::moduleImport("axios").getMember(method).getACall() and
+ method = [httpMethodName(), "request"]
}
private int getOptionsArgIndex() {
@@ -247,12 +242,10 @@ module ClientRequest {
method = "request" and
result = getOptionArgument(0, "data")
or
- (method = "post" or method = "put" or method = "put") and
- (result = getArgument(1) or result = getOptionArgument(2, "data"))
+ method = ["post", "put", "put"] and
+ result = [getArgument(1), getOptionArgument(2, "data")]
or
- exists(string name | name = "headers" or name = "params" |
- result = getOptionArgument([0 .. 2], name)
- )
+ result = getOptionArgument([0 .. 2], ["headers", "params"])
}
/** Gets the response type from the options passed in. */
From 99e98419dc3e38c06c2cf6ec6136d88efeae7af6 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 11 May 2021 11:24:21 +0200
Subject: [PATCH 105/168] add support for error values in an axios client
request
---
.../semmle/javascript/frameworks/ClientRequests.qll | 5 +++++
.../ClientRequests/ClientRequests.expected | 5 +++++
.../library-tests/frameworks/ClientRequests/tst.js | 13 +++++++++++++
3 files changed, 23 insertions(+)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
index 78f7ec92a16..477f9354d03 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
@@ -268,6 +268,11 @@ module ClientRequest {
responseType = getResponseType() and
promise = true and
result = this
+ or
+ responseType = getResponseType() and
+ promise = false and
+ result =
+ getReturn().getPromisedError().getMember("response").getMember("data").getAnImmediateUse()
}
}
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
index e448b888e12..c6542eb009d 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
@@ -87,6 +87,7 @@ test_ClientRequest
| tst.js:271:3:271:61 | proxy.w ... 080' }) |
| tst.js:274:1:283:2 | httpPro ... true\\n}) |
| tst.js:286:20:286:55 | new Web ... :8080') |
+| tst.js:296:5:299:6 | axios({ ... \\n }) |
test_getADataNode
| tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data |
| tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 |
@@ -227,6 +228,8 @@ test_getUrl
| tst.js:271:3:271:61 | proxy.w ... 080' }) | tst.js:271:33:271:58 | 'http:/ ... m:8080' |
| tst.js:274:1:283:2 | httpPro ... true\\n}) | tst.js:275:13:281:5 | {\\n ... ,\\n } |
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:286:34:286:54 | 'ws://l ... t:8080' |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:296:11:299:5 | {\\n ... ,\\n } |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:298:14:298:44 | "http:/ ... -axios" |
test_getAResponseDataNode
| tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true |
| tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true |
@@ -294,3 +297,5 @@ test_getAResponseDataNode
| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:67:235:70 | resp | fetch.response | false |
| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:73:235:76 | body | json | false |
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:291:44:291:53 | event.data | json | false |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:296:5:299:6 | axios({ ... \\n }) | json | true |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:303:26:303:42 | err.response.data | json | false |
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
index bc15565c072..f284ffaa407 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
@@ -290,4 +290,17 @@ function webSocket() {
socket.addEventListener('message', function (event) {
console.log("Data from server: " + event.data);
});
+}
+
+function moreAxios() {
+ axios({
+ method: 'GET',
+ url: "http://example.org/more-axios",
+ }).then(
+ x => res.send(x.data),
+ (err) => {
+ const status = err.response.status;
+ const data = err.response.data;
+ }
+ );
}
\ No newline at end of file
From 717070c7e439a1d99512a1f4238d157daef4cbc3 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Tue, 11 May 2021 13:11:35 +0200
Subject: [PATCH 106/168] Fix/cleanup passed and default arguments values
---
.../Entities/Types/FunctionPointerType.cs | 2 +-
.../Entities/Types/TupleType.cs | 2 +-
.../SymbolExtensions.cs | 18 +++++++++---------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs
index 37ba909ec46..4c3ab516172 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/FunctionPointerType.cs
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(EscapingTextWriter trapFile)
{
- Symbol.BuildTypeId(Context, trapFile, Symbol);
+ Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
trapFile.Write(";functionpointertype");
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
index ddbf1ac52a6..56db07671d7 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(EscapingTextWriter trapFile)
{
- Symbol.BuildTypeId(Context, trapFile, Symbol);
+ Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
trapFile.Write(";tuple");
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 91f0d0edf20..0bda977a6d5 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -158,7 +158,7 @@ namespace Semmle.Extraction.CSharp
/// The trap builder used to store the result.
/// The outer symbol being defined (to avoid recursive ids).
/// Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.
- public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false)
+ public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
using (cx.StackGuard)
{
@@ -166,7 +166,7 @@ namespace Semmle.Extraction.CSharp
{
case TypeKind.Array:
var array = (IArrayTypeSymbol)type;
- array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
+ array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
array.BuildArraySuffix(trapFile);
return;
case TypeKind.Class:
@@ -180,12 +180,12 @@ namespace Semmle.Extraction.CSharp
return;
case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type;
- ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
+ ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('*');
return;
case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type;
- tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
+ tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('_');
trapFile.Write(tp.Name);
return;
@@ -202,7 +202,7 @@ namespace Semmle.Extraction.CSharp
}
}
- private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false)
+ private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (symbol is null)
{
@@ -245,7 +245,7 @@ namespace Semmle.Extraction.CSharp
/// .
///
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
- symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, true);
+ symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
///
/// Constructs an array suffix string for this array type symbol.
@@ -292,7 +292,7 @@ namespace Semmle.Extraction.CSharp
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
trapFile.Write(":");
- f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
+ f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
}
);
trapFile.Write(")");
@@ -303,7 +303,7 @@ namespace Semmle.Extraction.CSharp
{
if (named.ContainingType is not null)
{
- named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined);
+ named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
trapFile.Write('.');
}
else if (named.ContainingNamespace is not null)
@@ -335,7 +335,7 @@ namespace Semmle.Extraction.CSharp
// a constructed type with different nullability of its members and methods,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
- ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined)
+ ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false)
);
trapFile.Write('>');
}
From 24d8abd2c2337aa21c048fe4f1cffed5b55cb41a Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 11 May 2021 14:27:53 +0200
Subject: [PATCH 107/168] C++: Add false positive testcase when an absolute
value is used in comparison.
---
.../semmle/tainted/ArithmeticTainted.expected | 4 ++++
.../Security/CWE/CWE-190/semmle/tainted/test5.cpp | 12 ++++++++++++
2 files changed, 16 insertions(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
index bdf00e0a5df..ee55beac3a2 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
@@ -3,6 +3,10 @@
| test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
+| test5.cpp:30:17:30:23 | tainted | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
+| test5.cpp:30:17:30:23 | tainted | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
+| test5.cpp:30:27:30:33 | tainted | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
+| test5.cpp:30:27:30:33 | tainted | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test.c:14:15:14:28 | maxConnections | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:14:15:14:28 | maxConnections | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:10 | len2 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:41:17:41:20 | argv | User-provided value |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
index 527c603d1b8..de0baa93bb1 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
@@ -18,3 +18,15 @@ void useTaintedInt()
y = getTaintedInt();
y = y * 1024; // BAD: arithmetic on a tainted value
}
+
+typedef long long int intmax_t;
+
+intmax_t imaxabs(intmax_t j);
+
+void useTaintedIntWithGuard() {
+ int tainted = getTaintedInt();
+
+ if(imaxabs(tainted) <= 100) {
+ int product = tainted * tainted; // GOOD: can't underflow/overflow [FALSE POSITIVE]
+ }
+}
\ No newline at end of file
From 0d9a85ca6b30511e41c1924161fae2193cec3b71 Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Tue, 11 May 2021 08:29:50 -0400
Subject: [PATCH 108/168] Update
java/change-notes/2021-05-05-kryo-improvements.md
Co-authored-by: Anders Schack-Mulligen
---
java/change-notes/2021-05-05-kryo-improvements.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/change-notes/2021-05-05-kryo-improvements.md b/java/change-notes/2021-05-05-kryo-improvements.md
index 5b39d1daae0..dbacb10099b 100644
--- a/java/change-notes/2021-05-05-kryo-improvements.md
+++ b/java/change-notes/2021-05-05-kryo-improvements.md
@@ -1,3 +1,3 @@
lgtm,codescanning
-* Add support for version 5 of the Kryo serialzation/deserialization framework.
+* Add support for version 5 of the Kryo serialization/deserialization framework.
* Add support for detecting safe uses of Kryo utilizing `KryoPool.Builder`. [#4992](https://github.com/github/codeql/issues/4992)
From 48e783184cd82692208d21d6286deeb38924804f Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 11 May 2021 14:30:28 +0200
Subject: [PATCH 109/168] C++: Fix false positive by recognizing more absolute
value functions in Overflow.qll
---
cpp/ql/src/semmle/code/cpp/security/Overflow.qll | 2 +-
.../CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected | 4 ----
.../query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp | 2 +-
3 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/src/semmle/code/cpp/security/Overflow.qll b/cpp/ql/src/semmle/code/cpp/security/Overflow.qll
index 6cf82791d52..b8ed406cb4a 100644
--- a/cpp/ql/src/semmle/code/cpp/security/Overflow.qll
+++ b/cpp/ql/src/semmle/code/cpp/security/Overflow.qll
@@ -12,7 +12,7 @@ import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
* Holds if the value of `use` is guarded using `abs`.
*/
predicate guardedAbs(Operation e, Expr use) {
- exists(FunctionCall fc | fc.getTarget().getName() = "abs" |
+ exists(FunctionCall fc | fc.getTarget().getName() = ["abs", "labs", "llabs", "imaxabs"] |
fc.getArgument(0).getAChild*() = use and
guardedLesser(e, fc)
)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
index ee55beac3a2..bdf00e0a5df 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected
@@ -3,10 +3,6 @@
| test5.cpp:17:6:17:18 | call to getTaintedInt | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:6 | y | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
-| test5.cpp:30:17:30:23 | tainted | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
-| test5.cpp:30:17:30:23 | tainted | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
-| test5.cpp:30:27:30:33 | tainted | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
-| test5.cpp:30:27:30:33 | tainted | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test.c:14:15:14:28 | maxConnections | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:14:15:14:28 | maxConnections | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:10 | len2 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:41:17:41:20 | argv | User-provided value |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
index de0baa93bb1..92eb71ad541 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
@@ -27,6 +27,6 @@ void useTaintedIntWithGuard() {
int tainted = getTaintedInt();
if(imaxabs(tainted) <= 100) {
- int product = tainted * tainted; // GOOD: can't underflow/overflow [FALSE POSITIVE]
+ int product = tainted * tainted; // GOOD: can't underflow/overflow
}
}
\ No newline at end of file
From d66506b0a388f40634f80318a4e8faedcf5909e7 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 11 May 2021 14:40:10 +0200
Subject: [PATCH 110/168] Data flow: Rename `{Argument,Parameter}NodeExt` to
`{Arg,Param}Node`
---
.../cpp/dataflow/internal/DataFlowImpl.qll | 112 ++++++++----------
.../cpp/dataflow/internal/DataFlowImpl2.qll | 112 ++++++++----------
.../cpp/dataflow/internal/DataFlowImpl3.qll | 112 ++++++++----------
.../cpp/dataflow/internal/DataFlowImpl4.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImplCommon.qll | 94 +++++++--------
.../dataflow/internal/DataFlowImplLocal.qll | 112 ++++++++----------
.../cpp/ir/dataflow/internal/DataFlowImpl.qll | 112 ++++++++----------
.../ir/dataflow/internal/DataFlowImpl2.qll | 112 ++++++++----------
.../ir/dataflow/internal/DataFlowImpl3.qll | 112 ++++++++----------
.../ir/dataflow/internal/DataFlowImpl4.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImplCommon.qll | 94 +++++++--------
.../csharp/dataflow/internal/DataFlowImpl.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImpl2.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImpl3.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImpl4.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImpl5.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImplCommon.qll | 94 +++++++--------
.../java/dataflow/internal/DataFlowImpl.qll | 112 ++++++++----------
.../java/dataflow/internal/DataFlowImpl2.qll | 112 ++++++++----------
.../java/dataflow/internal/DataFlowImpl3.qll | 112 ++++++++----------
.../java/dataflow/internal/DataFlowImpl4.qll | 112 ++++++++----------
.../java/dataflow/internal/DataFlowImpl5.qll | 112 ++++++++----------
.../java/dataflow/internal/DataFlowImpl6.qll | 112 ++++++++----------
.../dataflow/internal/DataFlowImplCommon.qll | 94 +++++++--------
.../dataflow/new/internal/DataFlowImpl.qll | 112 ++++++++----------
.../dataflow/new/internal/DataFlowImpl2.qll | 112 ++++++++----------
.../dataflow/new/internal/DataFlowImpl3.qll | 112 ++++++++----------
.../dataflow/new/internal/DataFlowImpl4.qll | 112 ++++++++----------
.../new/internal/DataFlowImplCommon.qll | 94 +++++++--------
29 files changed, 1372 insertions(+), 1786 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 cf83530bcbd..058d66b1496 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 b5ceabc605d..b8e08408911 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll
@@ -35,24 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
- ) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -120,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 ArgumentNodeExt or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -178,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -229,8 +227,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
- boolean toJump, DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
+ DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -276,7 +274,7 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
@@ -286,7 +284,7 @@ private module Cached {
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -296,7 +294,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNodeExt p, int pos |
+ exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -309,7 +307,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNodeExt or
+ n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -346,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -355,7 +353,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -397,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -415,27 +413,25 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(
- ParameterNodeExt p, ArgumentNodeExt arg, boolean read
- ) {
+ private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -447,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -456,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -469,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNodeExt p, Node n) {
+ predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -503,7 +499,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -517,7 +513,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -542,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArg(
- ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
- ) {
+ private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -583,7 +577,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -603,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
+ predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -616,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
+ ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -722,7 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -778,8 +772,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNodeExt).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
+ toPre.(ArgNode).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -827,7 +821,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -942,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
+ exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -1005,8 +999,8 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNodeExt extends Node {
- ParameterNodeExt() { parameterNode(this, _, _) }
+class ParamNode extends Node {
+ ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
@@ -1016,8 +1010,8 @@ class ParameterNodeExt extends Node {
}
/** A data-flow node that represents a call argument. */
-class ArgumentNodeExt extends Node {
- ArgumentNodeExt() { argumentNode(this, _, _) }
+class ArgNode extends Node {
+ ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
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 cf83530bcbd..058d66b1496 100644
--- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
+++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 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
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 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
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 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
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 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
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 b5ceabc605d..b8e08408911 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,24 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
- ) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -120,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 ArgumentNodeExt or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -178,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -229,8 +227,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
- boolean toJump, DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
+ DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -276,7 +274,7 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
@@ -286,7 +284,7 @@ private module Cached {
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -296,7 +294,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNodeExt p, int pos |
+ exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -309,7 +307,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNodeExt or
+ n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -346,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -355,7 +353,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -397,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -415,27 +413,25 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(
- ParameterNodeExt p, ArgumentNodeExt arg, boolean read
- ) {
+ private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -447,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -456,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -469,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNodeExt p, Node n) {
+ predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -503,7 +499,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -517,7 +513,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -542,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArg(
- ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
- ) {
+ private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -583,7 +577,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -603,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
+ predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -616,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
+ ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -722,7 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -778,8 +772,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNodeExt).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
+ toPre.(ArgNode).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -827,7 +821,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -942,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
+ exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -1005,8 +999,8 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNodeExt extends Node {
- ParameterNodeExt() { parameterNode(this, _, _) }
+class ParamNode extends Node {
+ ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
@@ -1016,8 +1010,8 @@ class ParameterNodeExt extends Node {
}
/** A data-flow node that represents a call argument. */
-class ArgumentNodeExt extends Node {
- ArgumentNodeExt() { argumentNode(this, _, _) }
+class ArgNode extends Node {
+ ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
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 cf83530bcbd..058d66b1496 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(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 b5ceabc605d..b8e08408911 100644
--- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
+++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll
@@ -35,24 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
- ) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -120,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 ArgumentNodeExt or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -178,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -229,8 +227,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
- boolean toJump, DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
+ DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -276,7 +274,7 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
@@ -286,7 +284,7 @@ private module Cached {
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -296,7 +294,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNodeExt p, int pos |
+ exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -309,7 +307,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNodeExt or
+ n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -346,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -355,7 +353,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -397,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -415,27 +413,25 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(
- ParameterNodeExt p, ArgumentNodeExt arg, boolean read
- ) {
+ private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -447,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -456,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -469,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNodeExt p, Node n) {
+ predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -503,7 +499,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -517,7 +513,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -542,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArg(
- ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
- ) {
+ private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -583,7 +577,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -603,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
+ predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -616,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
+ ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -722,7 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -778,8 +772,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNodeExt).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
+ toPre.(ArgNode).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -827,7 +821,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -942,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
+ exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -1005,8 +999,8 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNodeExt extends Node {
- ParameterNodeExt() { parameterNode(this, _, _) }
+class ParamNode extends Node {
+ ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
@@ -1016,8 +1010,8 @@ class ParameterNodeExt extends Node {
}
/** A data-flow node that represents a call argument. */
-class ArgumentNodeExt extends Node {
- ArgumentNodeExt() { argumentNode(this, _, _) }
+class ArgNode extends Node {
+ ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 b5ceabc605d..b8e08408911 100644
--- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll
+++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll
@@ -35,24 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
- ) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -120,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 ArgumentNodeExt or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -178,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -229,8 +227,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
- boolean toJump, DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
+ DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -276,7 +274,7 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
@@ -286,7 +284,7 @@ private module Cached {
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -296,7 +294,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNodeExt p, int pos |
+ exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -309,7 +307,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNodeExt or
+ n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -346,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -355,7 +353,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -397,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -415,27 +413,25 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(
- ParameterNodeExt p, ArgumentNodeExt arg, boolean read
- ) {
+ private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -447,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -456,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -469,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNodeExt p, Node n) {
+ predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -503,7 +499,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -517,7 +513,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -542,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArg(
- ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
- ) {
+ private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -583,7 +577,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -603,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
+ predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -616,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
+ ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -722,7 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -778,8 +772,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNodeExt).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
+ toPre.(ArgNode).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -827,7 +821,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -942,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
+ exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -1005,8 +999,8 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNodeExt extends Node {
- ParameterNodeExt() { parameterNode(this, _, _) }
+class ParamNode extends Node {
+ ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
@@ -1016,8 +1010,8 @@ class ParameterNodeExt extends Node {
}
/** A data-flow node that represents a call argument. */
-class ArgumentNodeExt extends Node {
- ArgumentNodeExt() { argumentNode(this, _, _) }
+class ArgNode extends Node {
+ ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
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 cf83530bcbd..058d66b1496 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 cf83530bcbd..058d66b1496 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll
@@ -385,7 +385,7 @@ private module Stage1 {
*/
pragma[nomagic]
private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
fwdFlow(arg, cc, config) and
viableParamArg(call, _, arg)
)
@@ -512,24 +512,22 @@ private module Stage1 {
pragma[nomagic]
predicate viableParamArgNodeCandFwd1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
viableParamArg(call, p, arg) and
fwdFlow(arg, config)
}
pragma[nomagic]
- private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, Configuration config
- ) {
- exists(ParameterNodeExt p |
+ private predicate revFlowIn(DataFlowCall call, ArgNode arg, boolean toReturn, Configuration config) {
+ exists(ParamNode p |
revFlow(p, toReturn, config) and
viableParamArgNodeCandFwd1(call, p, arg, config)
)
}
pragma[nomagic]
- private predicate revFlowInToReturn(DataFlowCall call, ArgumentNodeExt arg, Configuration config) {
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNode arg, Configuration config) {
revFlowIn(call, arg, true, config)
}
@@ -594,9 +592,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
returnFlowCallableNodeCand(c, kind, config) and
@@ -662,7 +658,7 @@ private predicate flowOutOfCallNodeCand1(
pragma[nomagic]
private predicate viableParamArgNodeCand1(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg, Configuration config
+ DataFlowCall call, ParamNode p, ArgNode arg, Configuration config
) {
Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
Stage1::revFlow(arg, config)
@@ -674,7 +670,7 @@ private predicate viableParamArgNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, Configuration config
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
@@ -734,8 +730,7 @@ private predicate flowOutOfCallNodeCand1(
*/
pragma[nomagic]
private predicate flowIntoCallNodeCand1(
- DataFlowCall call, ArgumentNodeExt arg, ParameterNodeExt p, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode arg, ParamNode p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, arg, p, config) and
exists(int b, int j |
@@ -943,10 +938,10 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -991,7 +986,7 @@ private module Stage2 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
)
@@ -1132,10 +1127,9 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1145,7 +1139,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1198,15 +1192,13 @@ private module Stage2 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -1246,8 +1238,7 @@ private predicate flowOutOfCallNodeCand2(
pragma[nomagic]
private predicate flowIntoCallNodeCand2(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
@@ -1276,7 +1267,7 @@ private module LocalFlowBigStep {
config.isSource(node) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
- node instanceof ParameterNodeExt or
+ node instanceof ParamNode or
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
@@ -1586,10 +1577,10 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -1634,7 +1625,7 @@ private module Stage3 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -1775,10 +1766,9 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -1788,7 +1778,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -1841,15 +1831,13 @@ private module Stage3 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2160,8 +2148,7 @@ private module Stage4 {
pragma[nomagic]
private predicate flowIntoCall(
- DataFlowCall call, ArgumentNodeExt node1, ParameterNodeExt node2, boolean allowsFieldFlow,
- Configuration config
+ DataFlowCall call, ArgNode node1, ParamNode node2, boolean allowsFieldFlow, Configuration config
) {
flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
@@ -2305,10 +2292,10 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParameterNodeExt p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ DataFlowCall call, ParamNode p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
Configuration config
) {
- exists(ArgumentNodeExt arg, boolean allowsFieldFlow |
+ exists(ArgNode arg, boolean allowsFieldFlow |
fwdFlow(arg, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
innercc = getCallContextCall(call, getNodeEnclosingCallable(p), outercc)
@@ -2353,7 +2340,7 @@ private module Stage4 {
private predicate fwdFlowIsEntered(
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
@@ -2494,10 +2481,9 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowIn(
- DataFlowCall call, ArgumentNodeExt arg, boolean toReturn, ApOption returnAp, Ap ap,
- Configuration config
+ DataFlowCall call, ArgNode arg, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(ParameterNodeExt p, boolean allowsFieldFlow |
+ exists(ParamNode p, boolean allowsFieldFlow |
revFlow(p, toReturn, returnAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config)
|
@@ -2507,7 +2493,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgumentNodeExt arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNode arg, Ap returnAp, Ap ap, Configuration config
) {
revFlowIn(call, arg, true, apSome(returnAp), ap, config)
}
@@ -2560,15 +2546,13 @@ private module Stage4 {
pragma[noinline]
private predicate parameterFlow(
- ParameterNodeExt p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ParamNode p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
revFlow(p, true, apSome(ap0), ap, config) and
c = getNodeEnclosingCallable(p)
}
- predicate parameterMayFlowThrough(
- ParameterNodeExt p, DataFlowCallable c, Ap ap, Configuration config
- ) {
+ predicate parameterMayFlowThrough(ParamNode p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnNodeExt ret, Ap ap0, ReturnKindExt kind, int pos |
parameterFlow(p, ap, ap0, c, config) and
c = getNodeEnclosingCallable(ret) and
@@ -2613,7 +2597,7 @@ private predicate nodeMayUseSummary(Node n, AccessPathApprox apa, Configuration
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParameterNodeExt p, AccessPath ap) {
+ TSummaryCtxSome(ParamNode p, AccessPath ap) {
Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
}
@@ -2634,7 +2618,7 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
- private ParameterNodeExt p;
+ private ParamNode p;
private AccessPath ap;
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
@@ -3242,7 +3226,7 @@ pragma[noinline]
private predicate pathIntoArg(
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3255,7 +3239,7 @@ pragma[noinline]
private predicate parameterCand(
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
) {
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
Stage4::revFlow(p, _, _, apa, config) and
p.isParameterOf(callable, i)
)
@@ -3279,7 +3263,7 @@ private predicate pathIntoCallable0(
* respectively.
*/
private predicate pathIntoCallable(
- PathNodeMid mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ PathNodeMid mid, ParamNode p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
DataFlowCall call
) {
exists(int i, DataFlowCallable callable, AccessPath ap |
@@ -3575,7 +3559,7 @@ private module FlowExploration {
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
- TSummaryCtx1Param(ParameterNodeExt p)
+ TSummaryCtx1Param(ParamNode p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
@@ -3931,7 +3915,7 @@ private module FlowExploration {
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
arg = mid.getNode() and
cc = mid.getCallContext() and
arg.argumentOf(call, i) and
@@ -3950,7 +3934,7 @@ private module FlowExploration {
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParameterNodeExt p, CallContext outercc, CallContextCall innercc,
+ PartialPathNodeFwd mid, ParamNode p, CallContext outercc, CallContextCall innercc,
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
Configuration config
) {
@@ -3987,7 +3971,7 @@ private module FlowExploration {
DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(ParameterNodeExt p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ exists(ParamNode p, CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
partialPathIntoCallable(mid, p, cc, innercc, sc1, sc2, call, _, config) and
paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
)
@@ -4044,7 +4028,7 @@ private module FlowExploration {
apConsRev(ap, c, ap0, config)
)
or
- exists(ParameterNodeExt p |
+ exists(ParamNode p |
mid.getNode() = p and
viableParamArg(_, p, node) and
sc1 = mid.getSummaryCtx1() and
@@ -4122,7 +4106,7 @@ private module FlowExploration {
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
Configuration config
) {
- exists(PartialPathNodeRev mid, ParameterNodeExt p |
+ exists(PartialPathNodeRev mid, ParamNode p |
mid.getNode() = p and
p.isParameterOf(_, pos) and
sc1 = mid.getSummaryCtx1() and
@@ -4145,7 +4129,7 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgumentNodeExt node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNode node, RevPartialAccessPath ap, Configuration config
) {
exists(DataFlowCall call, int pos |
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
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 b5ceabc605d..b8e08408911 100644
--- a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll
+++ b/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll
@@ -35,24 +35,22 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
*/
private module LambdaFlow {
- private predicate viableParamNonLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallable(call), i)
}
- private predicate viableParamLambda(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableLambda(call, _), i)
}
- private predicate viableParamArgNonLambda(
- DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg
- ) {
+ private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamNonLambda(call, i, p) and
arg.argumentOf(call, i)
)
}
- private predicate viableParamArgLambda(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParamLambda(call, i, p) and
arg.argumentOf(call, i)
@@ -120,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 ArgumentNodeExt or node instanceof ReturnNode
+ if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode
then compatibleTypes(t, getNodeDataFlowType(node))
else any()
}
@@ -178,7 +176,7 @@ private module LambdaFlow {
)
or
// flow into a callable
- exists(ParameterNodeExt p, DataFlowCallOption lastCall0, DataFlowCall call |
+ exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call |
revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and
(
if lastCall0 = TDataFlowCallNone() and toJump = false
@@ -229,8 +227,8 @@ private module LambdaFlow {
pragma[nomagic]
predicate revLambdaFlowIn(
- DataFlowCall lambdaCall, LambdaCallKind kind, ParameterNodeExt p, DataFlowType t,
- boolean toJump, DataFlowCallOption lastCall
+ DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump,
+ DataFlowCallOption lastCall
) {
revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall)
}
@@ -276,7 +274,7 @@ private module Cached {
predicate outNodeExt(Node n) {
n instanceof OutNode
or
- n.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNodeExt
+ n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode
}
cached
@@ -286,7 +284,7 @@ private module Cached {
OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) {
result = getAnOutNode(call, k.(ValueReturnKind).getKind())
or
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
result.(PostUpdateNode).getPreUpdateNode() = arg and
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
)
@@ -296,7 +294,7 @@ private module Cached {
predicate returnNodeExt(Node n, ReturnKindExt k) {
k = TValueReturn(n.(ReturnNode).getKind())
or
- exists(ParameterNodeExt p, int pos |
+ exists(ParamNode p, int pos |
parameterValueFlowsToPreUpdate(p, n) and
p.isParameterOf(_, pos) and
k = TParamUpdate(pos)
@@ -309,7 +307,7 @@ private module Cached {
cached
predicate castingNode(Node n) {
castNode(n) or
- n instanceof ParameterNodeExt or
+ n instanceof ParamNode or
n instanceof OutNodeExt or
// For reads, `x.f`, we want to check that the tracked type after the read (which
// is obtained by popping the head of the access path stack) is compatible with
@@ -346,7 +344,7 @@ private module Cached {
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
- private predicate viableParam(DataFlowCall call, int i, ParameterNodeExt p) {
+ private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
p.isParameterOf(viableCallableExt(call), i)
}
@@ -355,7 +353,7 @@ private module Cached {
* dispatch into account.
*/
cached
- predicate viableParamArg(DataFlowCall call, ParameterNodeExt p, ArgumentNodeExt arg) {
+ predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
@@ -397,7 +395,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to `node`.
*/
pragma[nomagic]
- private predicate parameterValueFlowCand(ParameterNodeExt p, Node node, boolean read) {
+ private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) {
p = node and
read = false
or
@@ -415,27 +413,25 @@ private module Cached {
)
or
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, false) and
argumentValueFlowsThroughCand(arg, node, read)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArgCand(p, arg, read) and
argumentValueFlowsThroughCand(arg, node, false)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArgCand(
- ParameterNodeExt p, ArgumentNodeExt arg, boolean read
- ) {
+ private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) {
parameterValueFlowCand(p, arg, read)
}
pragma[nomagic]
- predicate parameterValueFlowsToPreUpdateCand(ParameterNodeExt p, PostUpdateNode n) {
+ predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) {
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
}
@@ -447,7 +443,7 @@ private module Cached {
* `read` indicates whether it is contents of `p` that can flow to the return
* node.
*/
- predicate parameterValueFlowReturnCand(ParameterNodeExt p, ReturnKind kind, boolean read) {
+ predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) {
exists(ReturnNode ret |
parameterValueFlowCand(p, ret, read) and
kind = ret.getKind()
@@ -456,9 +452,9 @@ private module Cached {
pragma[nomagic]
private predicate argumentValueFlowsThroughCand0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, boolean read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturnCand(param, kind, read)
)
}
@@ -469,14 +465,14 @@ private module Cached {
*
* `read` indicates whether it is contents of `arg` that can flow to `out`.
*/
- predicate argumentValueFlowsThroughCand(ArgumentNodeExt arg, Node out, boolean read) {
+ predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThroughCand0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
)
}
- predicate cand(ParameterNodeExt p, Node n) {
+ predicate cand(ParamNode p, Node n) {
parameterValueFlowCand(p, n, _) and
(
parameterValueFlowReturnCand(p, _, _)
@@ -503,7 +499,7 @@ private module Cached {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
- predicate parameterValueFlow(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
if node instanceof CastingNode
then
@@ -517,7 +513,7 @@ private module Cached {
}
pragma[nomagic]
- private predicate parameterValueFlow0(ParameterNodeExt p, Node node, ReadStepTypesOption read) {
+ private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
@@ -542,34 +538,32 @@ private module Cached {
pragma[nomagic]
private predicate parameterValueFlow0_0(
- ReadStepTypesOption mustBeNone, ParameterNodeExt p, Node node, ReadStepTypesOption read
+ ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
- exists(ArgumentNodeExt arg |
+ exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
)
}
pragma[nomagic]
- private predicate parameterValueFlowArg(
- ParameterNodeExt p, ArgumentNodeExt arg, ReadStepTypesOption read
- ) {
+ private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
- DataFlowCall call, ArgumentNodeExt arg, ReturnKind kind, ReadStepTypesOption read
+ DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
) {
- exists(ParameterNodeExt param | viableParamArg(call, param, arg) |
+ exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
)
}
@@ -583,7 +577,7 @@ private module Cached {
* container type, and the content type.
*/
pragma[nomagic]
- predicate argumentValueFlowsThrough(ArgumentNodeExt arg, ReadStepTypesOption read, Node out) {
+ predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
out = getAnOutNode(call, kind)
@@ -603,7 +597,7 @@ private module Cached {
* value-preserving steps and a single read step, not taking call
* contexts into account, thus representing a getter-step.
*/
- predicate getterStep(ArgumentNodeExt arg, Content c, Node out) {
+ predicate getterStep(ArgNode arg, Content c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
}
@@ -616,7 +610,7 @@ private module Cached {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
- ParameterNodeExt p, ReturnKind kind, ReadStepTypesOption read
+ ParamNode p, ReturnKind kind, ReadStepTypesOption read
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
@@ -722,7 +716,7 @@ private module Cached {
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
*/
- private predicate parameterValueFlowsToPreUpdate(ParameterNodeExt p, PostUpdateNode n) {
+ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
}
@@ -778,8 +772,8 @@ private module Cached {
// Does the language-specific simpleLocalFlowStep already model flow
// from function input to output?
fromPre = getAnOutNode(c, _) and
- toPre.(ArgumentNodeExt).argumentOf(c, _) and
- simpleLocalFlowStep(toPre.(ArgumentNodeExt), fromPre)
+ toPre.(ArgNode).argumentOf(c, _) and
+ simpleLocalFlowStep(toPre.(ArgNode), fromPre)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
@@ -827,7 +821,7 @@ private module Cached {
cached
newtype TReturnKindExt =
TValueReturn(ReturnKind kind) or
- TParamUpdate(int pos) { exists(ParameterNodeExt p | p.isParameterOf(_, pos)) }
+ TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
cached
newtype TBooleanOption =
@@ -942,7 +936,7 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
override predicate relevantFor(DataFlowCallable callable) {
- exists(ParameterNodeExt p | getNodeEnclosingCallable(p) = callable)
+ exists(ParamNode p | getNodeEnclosingCallable(p) = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
@@ -1005,8 +999,8 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
-class ParameterNodeExt extends Node {
- ParameterNodeExt() { parameterNode(this, _, _) }
+class ParamNode extends Node {
+ ParamNode() { parameterNode(this, _, _) }
/**
* Holds if this node is the parameter of callable `c` at the specified
@@ -1016,8 +1010,8 @@ class ParameterNodeExt extends Node {
}
/** A data-flow node that represents a call argument. */
-class ArgumentNodeExt extends Node {
- ArgumentNodeExt() { argumentNode(this, _, _) }
+class ArgNode extends Node {
+ ArgNode() { argumentNode(this, _, _) }
/** Holds if this argument occurs at the given position in the given call. */
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
From 3e21f479a99e3bd5c85299755cc632c1c9da5383 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 11 May 2021 14:58:48 +0200
Subject: [PATCH 111/168] C++: Add change-note.
---
cpp/change-notes/2021-03-11-overflow-abs.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 cpp/change-notes/2021-03-11-overflow-abs.md
diff --git a/cpp/change-notes/2021-03-11-overflow-abs.md b/cpp/change-notes/2021-03-11-overflow-abs.md
new file mode 100644
index 00000000000..66854412f72
--- /dev/null
+++ b/cpp/change-notes/2021-03-11-overflow-abs.md
@@ -0,0 +1,2 @@
+lgtm
+* The `cpp/tainted-arithmetic`, `cpp/arithmetic-with-extreme-values`, and `cpp/uncontrolled-arithmetic` queries now recognize more functions as returning the absolute value of their input. As a result, they produce fewer false positives.
From 56b1f15ddaaeb5b53267293933b3850058678f6c Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Fri, 30 Apr 2021 19:18:35 -0400
Subject: [PATCH 112/168] [Java] Add taint tracking through Jackson
deserialization
---
.../jackson/JacksonSerializability.qll | 19 ++++++++
.../dataflow/taint-jackson/Test.java | 38 +++++++++++++--
.../dataflow/taint-jackson/dataFlow.expected | 48 -------------------
.../dataflow/taint-jackson/dataFlow.ql | 29 ++++++++---
.../jackson/databind/ObjectMapper.java | 4 ++
.../jackson/databind/ObjectReader.java | 45 +++++++++++++++++
6 files changed, 125 insertions(+), 58 deletions(-)
create mode 100644 java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 3356e31d965..c028af71d8d 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -50,6 +50,15 @@ library class JacksonWriteValueMethod extends Method, TaintPreservingCallable {
}
}
+library class JacksonReadValueMethod extends Method, TaintPreservingCallable {
+ JacksonReadValueMethod() {
+ getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") and
+ hasName("readValue")
+ }
+
+ override predicate returnsTaintFrom(int arg) { arg = 0 }
+}
+
/** A type whose values are explicitly serialized in a call to a Jackson method. */
library class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializableType {
ExplicitlyWrittenJacksonSerializableType() {
@@ -135,6 +144,16 @@ class JacksonDeserializableField extends DeserializableField {
}
}
+class JacksonDeserializableFieldAccess extends FieldAccess {
+ JacksonDeserializableFieldAccess() { getField() instanceof JacksonDeserializableField }
+}
+
+class JacksonDeseializedTaintStep extends AdditionalTaintStep {
+ override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
+ node2.asExpr().(JacksonDeserializableFieldAccess).getQualifier() = node1.asExpr()
+ }
+}
+
/**
* A call to the `addMixInAnnotations` or `addMixIn` Jackson method.
*
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
index 2caf9e4ee80..16b223ed2e8 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
@@ -8,28 +8,44 @@ import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.ObjectReader;
class Test {
+ public static class Potato {
+ private String name;
+
+ private String getName() {
+ return name;
+ }
+ }
+
public static String taint() {
return "tainted";
}
+ public static void sink(Object any) {}
+
public static void jacksonObjectMapper() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
String s = taint();
ObjectMapper om = new ObjectMapper();
File file = new File("testFile");
om.writeValue(file, s);
+ sink(file); //$hasTaintFlow
OutputStream out = new FileOutputStream(file);
om.writeValue(out, s);
+ sink(file); //$hasTaintFlow
Writer writer = new StringWriter();
om.writeValue(writer, s);
+ sink(writer); //$hasTaintFlow
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
om.writeValue(generator, s);
+ sink(generator); //$hasTaintFlow
String t = om.writeValueAsString(s);
- System.out.println(t);
+ sink(t); //$hasTaintFlow
byte[] bs = om.writeValueAsBytes(s);
String reconstructed = new String(bs, "utf-8");
- System.out.println(reconstructed);
+ sink(bs); //$hasTaintFlow
+ sink(reconstructed); //$hasTaintFlow
}
public static void jacksonObjectWriter() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
@@ -37,16 +53,30 @@ class Test {
ObjectWriter ow = new ObjectWriter();
File file = new File("testFile");
ow.writeValue(file, s);
+ sink(file); //$hasTaintFlow
OutputStream out = new FileOutputStream(file);
ow.writeValue(out, s);
+ sink(out); //$hasTaintFlow
Writer writer = new StringWriter();
ow.writeValue(writer, s);
+ sink(writer); //$hasTaintFlow
JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter());
ow.writeValue(generator, s);
+ sink(generator); //$hasTaintFlow
String t = ow.writeValueAsString(s);
- System.out.println(t);
+ sink(t); //$hasTaintFlow
byte[] bs = ow.writeValueAsBytes(s);
String reconstructed = new String(bs, "utf-8");
- System.out.println(reconstructed);
+ sink(bs); //$hasTaintFlow
+ sink(reconstructed); //$hasTaintFlow
+ }
+
+ public static void jacksonObjectReader() throws java.io.IOException {
+ String s = taint();
+ ObjectMapper om = new ObjectMapper();
+ ObjectReader reader = om.readerFor(Potato.class);
+ sink(reader.readValue(s)); //$hasTaintFlow
+ sink(reader.readValue(s, Potato.class).name); //$hasTaintFlow
+ sink(reader.readValue(s, Potato.class).getName()); //$hasTaintFlow
}
}
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected
index 122b21d50fe..e69de29bb2d 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.expected
@@ -1,48 +0,0 @@
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:10:43:10:54 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:13:73:13:84 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:16:44:16:55 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:19:36:19:47 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:22:35:22:46 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java:26:36:26:47 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:10:43:10:54 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:13:73:13:84 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:16:44:16:55 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:19:36:19:47 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:22:35:22:46 | value |
-| ../../../stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectWriter.java:26:36:26:47 | value |
-| Test.java:18:14:18:20 | taint(...) |
-| Test.java:21:17:21:20 | file [post update] |
-| Test.java:21:23:21:23 | s |
-| Test.java:22:43:22:46 | file |
-| Test.java:23:17:23:19 | out [post update] |
-| Test.java:23:22:23:22 | s |
-| Test.java:25:17:25:22 | writer [post update] |
-| Test.java:25:25:25:25 | s |
-| Test.java:27:17:27:25 | generator [post update] |
-| Test.java:27:28:27:28 | s |
-| Test.java:28:14:28:37 | writeValueAsString(...) |
-| Test.java:28:36:28:36 | s |
-| Test.java:29:22:29:22 | t |
-| Test.java:30:15:30:37 | writeValueAsBytes(...) |
-| Test.java:30:36:30:36 | s |
-| Test.java:31:26:31:48 | new String(...) |
-| Test.java:31:37:31:38 | bs |
-| Test.java:32:22:32:34 | reconstructed |
-| Test.java:36:14:36:20 | taint(...) |
-| Test.java:39:17:39:20 | file [post update] |
-| Test.java:39:23:39:23 | s |
-| Test.java:40:43:40:46 | file |
-| Test.java:41:17:41:19 | out [post update] |
-| Test.java:41:22:41:22 | s |
-| Test.java:43:17:43:22 | writer [post update] |
-| Test.java:43:25:43:25 | s |
-| Test.java:45:17:45:25 | generator [post update] |
-| Test.java:45:28:45:28 | s |
-| Test.java:46:14:46:37 | writeValueAsString(...) |
-| Test.java:46:36:46:36 | s |
-| Test.java:47:22:47:22 | t |
-| Test.java:48:15:48:37 | writeValueAsBytes(...) |
-| Test.java:48:36:48:36 | s |
-| Test.java:49:26:49:48 | new String(...) |
-| Test.java:49:37:49:38 | bs |
-| Test.java:50:22:50:34 | reconstructed |
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
index 333cf485f07..3ee51339b7b 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
@@ -1,17 +1,34 @@
+import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
+import TestUtilities.InlineExpectationsTest
class Conf extends TaintTracking::Configuration {
Conf() { this = "qltest:dataflow:jackson" }
- override predicate isSource(DataFlow::Node source) {
- source.asExpr().(MethodAccess).getMethod().hasName("taint")
+ override predicate isSource(DataFlow::Node n) {
+ n.asExpr().(MethodAccess).getMethod().hasName("taint")
+ or
+ n instanceof RemoteFlowSource
}
- override predicate isSink(DataFlow::Node sink) { any() }
+ override predicate isSink(DataFlow::Node n) {
+ exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument())
+ }
}
-from DataFlow::Node source, DataFlow::Node sink, Conf config
-where config.hasFlow(source, sink)
-select sink
+class HasFlowTest extends InlineExpectationsTest {
+ HasFlowTest() { this = "HasFlowTest" }
+
+ override string getARelevantTag() { result = "hasTaintFlow" }
+
+ override predicate hasActualResult(Location location, string element, string tag, string value) {
+ tag = "hasTaintFlow" and
+ exists(DataFlow::Node src, DataFlow::Node sink, Conf conf | conf.hasFlow(src, sink) |
+ sink.getLocation() = location and
+ element = sink.toString() and
+ value = ""
+ )
+ }
+}
\ No newline at end of file
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
index 455e0c0d309..af6218e4146 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -26,4 +26,8 @@ public class ObjectMapper {
public String writeValueAsString(Object value) {
return null;
}
+
+ public ObjectReader readerFor(Class> type) {
+ return null;
+ }
}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
new file mode 100644
index 00000000000..1916730da36
--- /dev/null
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
@@ -0,0 +1,45 @@
+package com.fasterxml.jackson.databind;
+
+import java.io.*;
+
+public class ObjectReader {
+ public ObjectReader forType(Class> valueType) {
+ return null;
+ }
+
+ public T readValue(String src) {
+ return null;
+ }
+
+ public T readValue(String src, Class valueType) throws IOException {
+ return null;
+ }
+
+ public T readValue(byte[] content) throws IOException {
+ return null;
+ }
+
+ public T readValue(byte[] content, Class valueType) throws IOException {
+ return null;
+ }
+
+ public T readValue(File src) throws IOException {
+ return null;
+ }
+
+ public T readValue(InputStream src) throws IOException {
+ return null;
+ }
+
+ public T readValue(InputStream src, Class valueType) throws IOException {
+ return null;
+ }
+
+ public T readValue(Reader src) throws IOException {
+ return null;
+ }
+
+ public T readValue(Reader src, Class valueType) throws IOException {
+ return null;
+ }
+}
\ No newline at end of file
From d0638db6e72836399061b506d029ad8a7d0e2f9d Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 3 May 2021 12:02:40 -0400
Subject: [PATCH 113/168] [Java] Add data flow through Iterator deserializers
for Jackson
---
.../jackson/JacksonSerializability.qll | 31 ++++++++++++----
.../dataflow/taint-jackson/Test.java | 15 ++++++++
.../jackson/databind/MappingIterator.java | 28 ++++++++++++++
.../jackson/databind/ObjectReader.java | 37 +++++++++++++++++++
4 files changed, 104 insertions(+), 7 deletions(-)
create mode 100644 java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index c028af71d8d..1cfe34d7167 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -28,7 +28,7 @@ abstract class JacksonSerializableType extends Type { }
* A method used for serializing objects using Jackson. The final parameter is the object to be
* serialized.
*/
-library class JacksonWriteValueMethod extends Method, TaintPreservingCallable {
+private class JacksonWriteValueMethod extends Method, TaintPreservingCallable {
JacksonWriteValueMethod() {
(
getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectWriter") or
@@ -50,17 +50,17 @@ library class JacksonWriteValueMethod extends Method, TaintPreservingCallable {
}
}
-library class JacksonReadValueMethod extends Method, TaintPreservingCallable {
+private class JacksonReadValueMethod extends Method, TaintPreservingCallable {
JacksonReadValueMethod() {
getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") and
- hasName("readValue")
+ hasName(["readValue", "readValues"])
}
override predicate returnsTaintFrom(int arg) { arg = 0 }
}
/** A type whose values are explicitly serialized in a call to a Jackson method. */
-library class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializableType {
+private class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializableType {
ExplicitlyWrittenJacksonSerializableType() {
exists(MethodAccess ma |
// A call to a Jackson write method...
@@ -71,8 +71,20 @@ library class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializab
}
}
+/** A type whose values are explicitly deserialized in a call to a Jackson method. */
+private class ExplicitlyReadJacksonSerializableType extends JacksonDeserializableType {
+ ExplicitlyReadJacksonSerializableType() {
+ exists(MethodAccess ma |
+ // A call to a Jackson write method...
+ ma.getMethod() instanceof JacksonReadValueMethod and
+ // ...where `this` is used in the final argument, indicating that this type will be deserialized.
+ usesType(ma.getArgument(ma.getNumArgument() - 1).getType(), this)
+ )
+ }
+}
+
/** A type used in a `JacksonSerializableField` declaration. */
-library class FieldReferencedJacksonSerializableType extends JacksonSerializableType {
+private class FieldReferencedJacksonSerializableType extends JacksonSerializableType {
FieldReferencedJacksonSerializableType() {
exists(JacksonSerializableField f | usesType(f.getType(), this))
}
@@ -105,7 +117,7 @@ private class TypeLiteralToJacksonDatabindFlowConfiguration extends DataFlow5::C
}
/** A type whose values are explicitly deserialized in a call to a Jackson method. */
-library class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializableType {
+private class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializableType {
ExplicitlyReadJacksonDeserializableType() {
exists(TypeLiteralToJacksonDatabindFlowConfiguration conf |
usesType(conf.getSourceWithFlowToJacksonDatabind().getTypeName().getType(), this)
@@ -114,7 +126,7 @@ library class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializa
}
/** A type used in a `JacksonDeserializableField` declaration. */
-library class FieldReferencedJacksonDeSerializableType extends JacksonDeserializableType {
+private class FieldReferencedJacksonDeSerializableType extends JacksonDeserializableType {
FieldReferencedJacksonDeSerializableType() {
exists(JacksonDeserializableField f | usesType(f.getType(), this))
}
@@ -144,10 +156,15 @@ class JacksonDeserializableField extends DeserializableField {
}
}
+/** A call to a field that may be deserialized using the Jackson JSON framework. */
class JacksonDeserializableFieldAccess extends FieldAccess {
JacksonDeserializableFieldAccess() { getField() instanceof JacksonDeserializableField }
}
+/**
+ * When an object is deserialized by the Jackson JSON framework using a tainted input source,
+ * the fields that the framework deserialized are themselves tainted input data.
+ */
class JacksonDeseializedTaintStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
node2.asExpr().(JacksonDeserializableFieldAccess).getQualifier() = node1.asExpr()
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
index 16b223ed2e8..26f9182339a 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
@@ -3,6 +3,7 @@ import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
+import java.util.Iterator;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -79,4 +80,18 @@ class Test {
sink(reader.readValue(s, Potato.class).name); //$hasTaintFlow
sink(reader.readValue(s, Potato.class).getName()); //$hasTaintFlow
}
+
+ public static void jacksonObjectReaderIterable() throws java.io.IOException {
+ String s = taint();
+ ObjectMapper om = new ObjectMapper();
+ ObjectReader reader = om.readerFor(Potato.class);
+ sink(reader.readValues(s)); //$hasTaintFlow
+ Iterator pIterator = reader.readValues(s, Potato.class);
+ while(pIterator.hasNext()) {
+ Potato p = pIterator.next();
+ sink(p); //$hasTaintFlow
+ sink(p.name); //$hasTaintFlow
+ sink(p.getName()); //$hasTaintFlow
+ }
+ }
}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
new file mode 100644
index 00000000000..72e08df2719
--- /dev/null
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
@@ -0,0 +1,28 @@
+package com.fasterxml.jackson.databind;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.*;
+
+public class MappingIterator implements Iterator, Closeable {
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public T next() {
+ return null;
+ }
+
+ @Override
+ public void remove() {
+
+ }
+
+ @Override
+ public void close() throws IOException {
+
+ }
+}
\ No newline at end of file
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
index 1916730da36..875c07dace3 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
@@ -42,4 +42,41 @@ public class ObjectReader {
public T readValue(Reader src, Class valueType) throws IOException {
return null;
}
+
+ public MappingIterator readValues(String src) {
+ return null;
+ }
+
+ public MappingIterator readValues(String src, Class valueType) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(byte[] content) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(byte[] content, Class valueType) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(File src) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(InputStream src) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(InputStream src, Class valueType) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(Reader src) throws IOException {
+ return null;
+ }
+
+ public MappingIterator readValues(Reader src, Class valueType) throws IOException {
+ return null;
+ }
+
}
\ No newline at end of file
From d0b0b767a28d98ce40d3c2fddee477608757cdcd Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 3 May 2021 12:23:33 -0400
Subject: [PATCH 114/168] Apply suggestions from code review
Co-authored-by: Marcono1234
---
.../code/java/frameworks/jackson/JacksonSerializability.qll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 1cfe34d7167..2ddb12e828d 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -75,7 +75,7 @@ private class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializab
private class ExplicitlyReadJacksonSerializableType extends JacksonDeserializableType {
ExplicitlyReadJacksonSerializableType() {
exists(MethodAccess ma |
- // A call to a Jackson write method...
+ // A call to a Jackson read method...
ma.getMethod() instanceof JacksonReadValueMethod and
// ...where `this` is used in the final argument, indicating that this type will be deserialized.
usesType(ma.getArgument(ma.getNumArgument() - 1).getType(), this)
@@ -126,8 +126,8 @@ private class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializa
}
/** A type used in a `JacksonDeserializableField` declaration. */
-private class FieldReferencedJacksonDeSerializableType extends JacksonDeserializableType {
- FieldReferencedJacksonDeSerializableType() {
+private class FieldReferencedJacksonDeserializableType extends JacksonDeserializableType {
+ FieldReferencedJacksonDeserializableType() {
exists(JacksonDeserializableField f | usesType(f.getType(), this))
}
}
From b871f48c509b960c75847903300f7cbf7664fb6a Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 3 May 2021 12:40:48 -0400
Subject: [PATCH 115/168] [Java] Add release note to Jackson change
---
.../change-notes/2021-05-03-jackson-dataflow-deserialization.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 java/change-notes/2021-05-03-jackson-dataflow-deserialization.md
diff --git a/java/change-notes/2021-05-03-jackson-dataflow-deserialization.md b/java/change-notes/2021-05-03-jackson-dataflow-deserialization.md
new file mode 100644
index 00000000000..475f8dbee4f
--- /dev/null
+++ b/java/change-notes/2021-05-03-jackson-dataflow-deserialization.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* Increase coverage of dataflow through Jackson JSON deserialized objects.
From 83d527ed190331f4ecdb165539423922ee1f704a Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 3 May 2021 13:39:54 -0400
Subject: [PATCH 116/168] Apply suggestions from code review
Co-authored-by: Marcono1234
---
.../code/java/frameworks/jackson/JacksonSerializability.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 2ddb12e828d..0b75aff2b24 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -165,7 +165,7 @@ class JacksonDeserializableFieldAccess extends FieldAccess {
* When an object is deserialized by the Jackson JSON framework using a tainted input source,
* the fields that the framework deserialized are themselves tainted input data.
*/
-class JacksonDeseializedTaintStep extends AdditionalTaintStep {
+class JacksonDeserializedTaintStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
node2.asExpr().(JacksonDeserializableFieldAccess).getQualifier() = node1.asExpr()
}
From e97bad3b3395d3a6143b515bba1b12c344a881d2 Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Tue, 4 May 2021 10:58:20 -0400
Subject: [PATCH 117/168] Support field access data flow for
JacksonDeserializedTaintStep
---
.../code/java/frameworks/jackson/JacksonSerializability.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 0b75aff2b24..8cc70c5f36a 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -167,7 +167,7 @@ class JacksonDeserializableFieldAccess extends FieldAccess {
*/
class JacksonDeserializedTaintStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
- node2.asExpr().(JacksonDeserializableFieldAccess).getQualifier() = node1.asExpr()
+ DataFlow::getFieldQualifier(node2.asExpr().(JacksonDeserializableFieldAccess)) = node1
}
}
From bacc3ef5b3699f03bff628e8ca1196c0f7095342 Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Mon, 10 May 2021 17:20:14 -0400
Subject: [PATCH 118/168] [Java] Jackson add support for 2 step deserialization
taint flow
---
.../semmle/code/java/dataflow/ExternalFlow.qll | 1 +
.../frameworks/jackson/JacksonSerializability.qll | 11 +++++++++++
.../dataflow/taint-jackson/Test.java | 15 +++++++++++++++
.../com/fasterxml/jackson/databind/JsonNode.java | 4 +++-
.../fasterxml/jackson/databind/ObjectMapper.java | 8 ++++++++
5 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
index df529b49efb..1ec81d1e3ac 100644
--- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
+++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll
@@ -77,6 +77,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.ApacheHttp
private import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.frameworks.guava.Guava
+ private import semmle.code.java.frameworks.jackson.JacksonSerializability
private import semmle.code.java.security.ResponseSplitting
private import semmle.code.java.security.XSS
private import semmle.code.java.security.LdapInjection
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 8cc70c5f36a..ad35a802d43 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -9,6 +9,7 @@ import semmle.code.java.Reflection
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow5
import semmle.code.java.dataflow.FlowSteps
+private import semmle.code.java.dataflow.ExternalFlow
/**
* A `@com.fasterxml.jackson.annotation.JsonIgnore` annoation.
@@ -275,3 +276,13 @@ class JacksonMixedInCallable extends Callable {
)
}
}
+
+private class JacksonModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "com.fasterxml.jackson.databind;ObjectMapper;true;valueToTree;;;Argument[0];ReturnValue;taint",
+ "com.fasterxml.jackson.databind;ObjectMapper;true;convertValue;;;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
index 26f9182339a..3be85336e26 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java
@@ -4,9 +4,12 @@ import java.io.OutputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.ObjectReader;
@@ -94,4 +97,16 @@ class Test {
sink(p.getName()); //$hasTaintFlow
}
}
+
+ public static void jacksonTwoStepDeserialization() throws java.io.IOException {
+ String s = taint();
+ Map taintedParams = new HashMap<>();
+ taintedParams.put("name", s);
+ ObjectMapper om = new ObjectMapper();
+ JsonNode jn = om.valueToTree(taintedParams);
+ sink(jn); //$hasTaintFlow
+ Potato p = om.convertValue(jn, Potato.class);
+ sink(p); //$hasTaintFlow
+ sink(p.getName()); //$hasTaintFlow
+ }
}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
index a26eb2592c6..ad3da15a26c 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
@@ -1,6 +1,8 @@
package com.fasterxml.jackson.databind;
-public class JsonNode {
+import java.util.*;
+
+public abstract class JsonNode implements Iterable {
public JsonNode() {
}
}
\ No newline at end of file
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
index af6218e4146..71dc99a351d 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -30,4 +30,12 @@ public class ObjectMapper {
public ObjectReader readerFor(Class> type) {
return null;
}
+
+ public T valueToTree(Object fromValue) throws IllegalArgumentException {
+ return null;
+ }
+
+ public T convertValue(Object fromValue, Class toValueType) throws IllegalArgumentException {
+ return null;
+ }
}
From 5a68ac88efdf272c2f3e6dd9a9c5393b582bbcec Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Tue, 11 May 2021 10:48:22 -0400
Subject: [PATCH 119/168] Cleanup Jackson logic after code review
---
.../jackson/JacksonSerializability.qll | 19 +++++++------------
.../dataflow/taint-jackson/dataFlow.ql | 2 +-
.../fasterxml/jackson/databind/JsonNode.java | 2 +-
.../jackson/databind/MappingIterator.java | 2 +-
.../jackson/databind/ObjectReader.java | 2 +-
5 files changed, 11 insertions(+), 16 deletions(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index ad35a802d43..09fd419642e 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -72,18 +72,6 @@ private class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializab
}
}
-/** A type whose values are explicitly deserialized in a call to a Jackson method. */
-private class ExplicitlyReadJacksonSerializableType extends JacksonDeserializableType {
- ExplicitlyReadJacksonSerializableType() {
- exists(MethodAccess ma |
- // A call to a Jackson read method...
- ma.getMethod() instanceof JacksonReadValueMethod and
- // ...where `this` is used in the final argument, indicating that this type will be deserialized.
- usesType(ma.getArgument(ma.getNumArgument() - 1).getType(), this)
- )
- }
-}
-
/** A type used in a `JacksonSerializableField` declaration. */
private class FieldReferencedJacksonSerializableType extends JacksonSerializableType {
FieldReferencedJacksonSerializableType() {
@@ -123,6 +111,13 @@ private class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializa
exists(TypeLiteralToJacksonDatabindFlowConfiguration conf |
usesType(conf.getSourceWithFlowToJacksonDatabind().getTypeName().getType(), this)
)
+ or
+ exists(MethodAccess ma |
+ // A call to a Jackson read method...
+ ma.getMethod() instanceof JacksonReadValueMethod and
+ // ...where `this` is used in the final argument, indicating that this type will be deserialized.
+ usesType(ma.getArgument(ma.getNumArgument() - 1).getType(), this)
+ )
}
}
diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
index 3ee51339b7b..0836906530b 100644
--- a/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
+++ b/java/ql/test/library-tests/dataflow/taint-jackson/dataFlow.ql
@@ -31,4 +31,4 @@ class HasFlowTest extends InlineExpectationsTest {
value = ""
)
}
-}
\ No newline at end of file
+}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
index ad3da15a26c..b04572cd4da 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/JsonNode.java
@@ -5,4 +5,4 @@ import java.util.*;
public abstract class JsonNode implements Iterable {
public JsonNode() {
}
-}
\ No newline at end of file
+}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
index 72e08df2719..ac427ef01c9 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/MappingIterator.java
@@ -25,4 +25,4 @@ public class MappingIterator implements Iterator, Closeable {
public void close() throws IOException {
}
-}
\ No newline at end of file
+}
diff --git a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
index 875c07dace3..f067a3e95a4 100644
--- a/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/java/ql/test/stubs/jackson-databind-2.10/com/fasterxml/jackson/databind/ObjectReader.java
@@ -79,4 +79,4 @@ public class ObjectReader {
return null;
}
-}
\ No newline at end of file
+}
From e7cd6c997208b742129bd72c0715a27790130211 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 11 May 2021 16:56:12 +0000
Subject: [PATCH 120/168] Optimize the query
---
.../Security/CWE/CWE-094/JythonInjection.java | 6 ++--
.../Security/CWE/CWE-094/JythonInjection.ql | 35 +++++++++----------
.../security/CWE-094/JythonInjection.java | 4 +--
3 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.java b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.java
index fca518443d1..5c1796e1f60 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.java
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.java
@@ -1,3 +1,5 @@
+import org.python.util.PythonInterpreter;
+
public class JythonInjection extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
@@ -10,7 +12,7 @@ public class JythonInjection extends HttpServlet {
interpreter.setOut(out);
interpreter.setErr(out);
- // BAD: allow arbitrary Jython expression to execute
+ // BAD: allow execution of arbitrary Python code
interpreter.exec(code);
out.flush();
@@ -32,7 +34,7 @@ public class JythonInjection extends HttpServlet {
try {
interpreter = new PythonInterpreter();
- // BAD: allow arbitrary Jython expression to evaluate
+ // BAD: allow execution of arbitrary Python code
PyObject py = interpreter.eval(code);
response.getWriter().print(py.toString());
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
index 088c33e00fd..9991c0901dc 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
@@ -11,6 +11,7 @@
import java
import semmle.code.java.dataflow.FlowSources
+import semmle.code.java.frameworks.spring.SpringController
import DataFlow::PathGraph
/** The class `org.python.util.PythonInterpreter`. */
@@ -22,12 +23,7 @@ class PythonInterpreter extends RefType {
class InterpretExprMethod extends Method {
InterpretExprMethod() {
this.getDeclaringType().getAnAncestor*() instanceof PythonInterpreter and
- (
- getName().matches("exec%") or
- hasName("eval") or
- hasName("compile") or
- getName().matches("run%")
- )
+ getName().matches(["exec%", "run%", "eval", "compile"])
}
}
@@ -48,14 +44,14 @@ predicate runCode(MethodAccess ma, Expr sink) {
class LoadClassMethod extends Method {
LoadClassMethod() {
this.getDeclaringType().getAnAncestor*() instanceof BytecodeLoader and
- (
- hasName("makeClass") or
- hasName("makeCode")
- )
+ hasName(["makeClass", "makeCode"])
}
}
-/** Holds if a Java class file is loaded. */
+/**
+ * Holds if `ma` is a call to a class-loading method, and `sink` is the byte array
+ * representing the class to be loaded.
+ */
predicate loadClass(MethodAccess ma, Expr sink) {
exists(Method m, int i | m = ma.getMethod() |
m instanceof LoadClassMethod and
@@ -69,7 +65,7 @@ class Py extends RefType {
Py() { this.hasQualifiedName("org.python.core", "Py") }
}
-/** A method that compiles code with `Py`. */
+/** A method declared on class `Py` or one of its descendants that compiles Python code. */
class PyCompileMethod extends Method {
PyCompileMethod() {
this.getDeclaringType().getAnAncestor*() instanceof Py and
@@ -85,7 +81,7 @@ predicate compile(MethodAccess ma, Expr sink) {
)
}
-/** Sink of an expression loaded by Jython. */
+/** An expression loaded by Jython. */
class CodeInjectionSink extends DataFlow::ExprNode {
CodeInjectionSink() {
runCode(_, this.getExpr()) or
@@ -103,17 +99,18 @@ class CodeInjectionSink extends DataFlow::ExprNode {
class CodeInjectionConfiguration extends TaintTracking::Configuration {
CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
- override predicate isSource(DataFlow::Node source) {
- source instanceof RemoteFlowSource
- or
- source instanceof LocalUserInput
- }
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
// @RequestBody MyQueryObj query; interpreter.exec(query.getInterpreterCode());
- exists(MethodAccess ma | ma.getQualifier() = node1.asExpr() and ma = node2.asExpr())
+ exists(MethodAccess ma |
+ ma.getMethod().getDeclaringType().getASubtype*() instanceof SpringUntrustedDataType and
+ not ma.getMethod().getDeclaringType() instanceof TypeObject and
+ ma.getQualifier() = node1.asExpr() and
+ ma = node2.asExpr()
+ )
}
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
index 682e8af5113..f9b29fec6cc 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/JythonInjection.java
@@ -22,7 +22,7 @@ public class JythonInjection extends HttpServlet {
super();
}
- // BAD: allow arbitrary Jython expression to execute
+ // BAD: allow execution of arbitrary Python code
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
@@ -47,7 +47,7 @@ public class JythonInjection extends HttpServlet {
}
}
- // BAD: allow arbitrary Jython expression to evaluate
+ // BAD: allow execution of arbitrary Python code
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
String code = request.getParameter("code");
From 948f1d8e344935c7b550450813e61f4df415ba6e Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 11 May 2021 19:43:21 +0200
Subject: [PATCH 121/168] C++: Add testcase with INTMAX_MIN.
---
.../Security/CWE/CWE-190/semmle/tainted/test5.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
index 92eb71ad541..2ee675be6b5 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/test5.cpp
@@ -29,4 +29,14 @@ void useTaintedIntWithGuard() {
if(imaxabs(tainted) <= 100) {
int product = tainted * tainted; // GOOD: can't underflow/overflow
}
+}
+
+#define INTMAX_MIN (-0x7fffffffffffffff - 1)
+
+void useTaintedIntWithGuardIntMaxMin() {
+ intmax_t tainted = getTaintedInt();
+
+ if(imaxabs(tainted) <= INTMAX_MIN) {
+ int product = tainted * tainted; // BAD: imaxabs(INTMAX_MIN) == INTMAX_MIN [NOT DETECTED]
+ }
}
\ No newline at end of file
From 8e371fd05a842648d78762238c4f2b8cd5c531f4 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Tue, 11 May 2021 21:54:05 +0200
Subject: [PATCH 122/168] Adjust expected IR test file
---
csharp/ql/test/experimental/ir/ir/raw_ir.expected | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/csharp/ql/test/experimental/ir/ir/raw_ir.expected b/csharp/ql/test/experimental/ir/ir/raw_ir.expected
index 646cd0f26f9..c598a8778d9 100644
--- a/csharp/ql/test/experimental/ir/ir/raw_ir.expected
+++ b/csharp/ql/test/experimental/ir/ir/raw_ir.expected
@@ -613,13 +613,13 @@ foreach.cs:
# 5| r5_28(glval) = PointerAdd[4] : r5_1, r5_27
# 5| r5_29(Int32) = Constant[7] :
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
-# 7| r7_1(glval) = VariableAddress[#temp7:9] :
+# 7| r7_1(glval) = VariableAddress[#temp7:9] :
# 7| r7_2(glval) = VariableAddress[a_array] :
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
# 7| r7_4() = FunctionAddress[GetEnumerator] :
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
# 7| mu7_6() = ^CallSideEffect : ~m?
-# 7| mu7_7(IEnumerator) = Store[#temp7:9] : &:r7_1, r7_5
+# 7| mu7_7(Boolean) = Store[#temp7:9] : &:r7_1, r7_5
#-----| Goto -> Block 1
# 7| Block 1
From 961467e06e4142ca71d144ee5c1bb7ca993b706b Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 12 May 2021 10:15:04 +0200
Subject: [PATCH 123/168] C#: Always pass `/p:UseSharedCompilation=false` to
`dotnet build` in auto builder
---
.../BuildScripts.cs | 44 ++++-----------
.../Semmle.Autobuild.CSharp/DotNetRule.cs | 56 ++++---------------
2 files changed, 21 insertions(+), 79 deletions(-)
diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs
index 99ad4c8f963..197edc2c162 100644
--- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs
+++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs
@@ -415,7 +415,7 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet restore C:\Project\test.csproj"] = 0;
- actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental C:\Project\test.csproj"] = 0;
+ actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -439,9 +439,6 @@ namespace Semmle.Autobuild.CSharp.Tests
[Fact]
public void TestLinuxCSharpAutoBuilder()
{
- actions.RunProcess["dotnet --list-runtimes"] = 0;
- actions.RunProcessOut["dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
-Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]";
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
@@ -463,7 +460,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.LoadXml[@"C:\Project/test.csproj"] = xml;
var autobuilder = CreateAutoBuilder(false);
- TestAutobuilderScript(autobuilder, 0, 5);
+ TestAutobuilderScript(autobuilder, 0, 4);
}
[Fact]
@@ -603,8 +600,6 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
[Fact]
public void TestLinuxBuildCommand()
{
- actions.RunProcess["dotnet --list-runtimes"] = 1;
- actions.RunProcessOut["dotnet --list-runtimes"] = "";
actions.RunProcess[@"C:\odasa/tools/odasa index --auto ""./build.sh --skip-tests"""] = 0;
actions.FileExists["csharp.log"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -615,7 +610,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
SkipVsWhere();
var autobuilder = CreateAutoBuilder(false, buildCommand: "./build.sh --skip-tests");
- TestAutobuilderScript(autobuilder, 0, 2);
+ TestAutobuilderScript(autobuilder, 0, 1);
}
[Fact]
@@ -626,14 +621,12 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.RunProcess[@"/bin/chmod u+x C:\Project/build/build.sh"] = 0;
- actions.RunProcess["dotnet --list-runtimes"] = 1;
- actions.RunProcessOut["dotnet --list-runtimes"] = "";
actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/build/build.sh"] = 0;
actions.RunProcessWorkingDirectory[@"C:\odasa/tools/odasa index --auto C:\Project/build/build.sh"] = @"C:\Project/build";
actions.FileExists["csharp.log"] = true;
var autobuilder = CreateAutoBuilder(false);
- TestAutobuilderScript(autobuilder, 0, 3);
+ TestAutobuilderScript(autobuilder, 0, 2);
}
[Fact]
@@ -645,14 +638,12 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.RunProcess[@"/bin/chmod u+x C:\Project/build.sh"] = 0;
- actions.RunProcess["dotnet --list-runtimes"] = 1;
- actions.RunProcessOut["dotnet --list-runtimes"] = "";
actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/build.sh"] = 0;
actions.RunProcessWorkingDirectory[@"C:\odasa/tools/odasa index --auto C:\Project/build.sh"] = @"C:\Project";
actions.FileExists["csharp.log"] = false;
var autobuilder = CreateAutoBuilder(false);
- TestAutobuilderScript(autobuilder, 1, 3);
+ TestAutobuilderScript(autobuilder, 1, 2);
}
[Fact]
@@ -664,14 +655,12 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
actions.RunProcess[@"/bin/chmod u+x C:\Project/build.sh"] = 0;
- actions.RunProcess["dotnet --list-runtimes"] = 1;
- actions.RunProcessOut["dotnet --list-runtimes"] = "";
actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/build.sh"] = 5;
actions.RunProcessWorkingDirectory[@"C:\odasa/tools/odasa index --auto C:\Project/build.sh"] = @"C:\Project";
actions.FileExists["csharp.log"] = true;
var autobuilder = CreateAutoBuilder(false);
- TestAutobuilderScript(autobuilder, 1, 3);
+ TestAutobuilderScript(autobuilder, 1, 2);
}
[Fact]
@@ -872,9 +861,6 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
[Fact]
public void TestSkipNugetDotnet()
{
- actions.RunProcess["dotnet --list-runtimes"] = 0;
- actions.RunProcessOut["dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
-Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]";
actions.RunProcess["dotnet --info"] = 0;
actions.RunProcess[@"dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"dotnet restore C:\Project/test.csproj"] = 0;
@@ -896,7 +882,7 @@ Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.LoadXml[@"C:\Project/test.csproj"] = xml;
var autobuilder = CreateAutoBuilder(false, dotnetArguments: "--no-restore"); // nugetRestore=false does not work for now.
- TestAutobuilderScript(autobuilder, 0, 5);
+ TestAutobuilderScript(autobuilder, 0, 4);
}
[Fact]
@@ -907,13 +893,10 @@ Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0;
actions.RunProcess[@"./dotnet-install.sh --channel release --version 2.1.3 --install-dir C:\Project/.dotnet"] = 0;
actions.RunProcess[@"rm dotnet-install.sh"] = 0;
- actions.RunProcess[@"C:\Project/.dotnet/dotnet --list-runtimes"] = 0;
- actions.RunProcessOut[@"C:\Project/.dotnet/dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
-Microsoft.NETCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]";
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
- actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/.dotnet/dotnet build --no-incremental C:\Project/test.csproj"] = 0;
+ actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project/test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists["test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
@@ -933,7 +916,7 @@ Microsoft.NETCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.DownloadFiles.Add(("https://dot.net/v1/dotnet-install.sh", "dotnet-install.sh"));
var autobuilder = CreateAutoBuilder(false, dotnetVersion: "2.1.3");
- TestAutobuilderScript(autobuilder, 0, 9);
+ TestAutobuilderScript(autobuilder, 0, 8);
}
[Fact]
@@ -945,11 +928,6 @@ Microsoft.NETCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0;
actions.RunProcess[@"./dotnet-install.sh --channel release --version 2.1.3 --install-dir C:\Project/.dotnet"] = 0;
actions.RunProcess[@"rm dotnet-install.sh"] = 0;
- actions.RunProcess[@"C:\Project/.dotnet/dotnet --list-runtimes"] = 0;
- actions.RunProcessOut[@"C:\Project/.dotnet/dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
-Microsoft.AspNetCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
-Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
-Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]";
actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet clean C:\Project/test.csproj"] = 0;
actions.RunProcess[@"C:\Project/.dotnet/dotnet restore C:\Project/test.csproj"] = 0;
@@ -973,7 +951,7 @@ Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.DownloadFiles.Add(("https://dot.net/v1/dotnet-install.sh", "dotnet-install.sh"));
var autobuilder = CreateAutoBuilder(false, dotnetVersion: "2.1.3");
- TestAutobuilderScript(autobuilder, 0, 9);
+ TestAutobuilderScript(autobuilder, 0, 8);
}
private void TestDotnetVersionWindows(Action action, int commandsRun)
@@ -984,7 +962,7 @@ Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean C:\Project\test.csproj"] = 0;
actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore C:\Project\test.csproj"] = 0;
- actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental C:\Project\test.csproj"] = 0;
+ actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false C:\Project\test.csproj"] = 0;
actions.FileExists["csharp.log"] = true;
actions.FileExists[@"C:\Project\test.csproj"] = true;
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
index a456c9407db..955775d0f66 100644
--- a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
+++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
@@ -36,7 +36,7 @@ namespace Semmle.Autobuild.CSharp
builder.Log(Severity.Info, "Attempting to build using .NET Core");
}
- return WithDotNet(builder, (dotNetPath, environment, compatibleClr) =>
+ return WithDotNet(builder, (dotNetPath, environment) =>
{
var ret = GetInfoCommand(builder.Actions, dotNetPath, environment);
foreach (var projectOrSolution in builder.ProjectsOrSolutionsToBuild)
@@ -49,7 +49,7 @@ namespace Semmle.Autobuild.CSharp
restoreCommand.QuoteArgument(projectOrSolution.FullPath);
var restore = restoreCommand.Script;
- var build = GetBuildScript(builder, dotNetPath, environment, compatibleClr, projectOrSolution.FullPath);
+ var build = GetBuildScript(builder, dotNetPath, environment, projectOrSolution.FullPath);
ret &= BuildScript.Try(clean) & BuildScript.Try(restore) & build;
}
@@ -57,7 +57,7 @@ namespace Semmle.Autobuild.CSharp
});
}
- private static BuildScript WithDotNet(Autobuilder builder, Func?, bool, BuildScript> f)
+ private static BuildScript WithDotNet(Autobuilder builder, Func?, BuildScript> f)
{
var installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet");
var installScript = DownloadDotNet(builder, installDir);
@@ -81,35 +81,10 @@ namespace Semmle.Autobuild.CSharp
env = null;
}
- // The CLR tracer is always compatible on Windows
- if (builder.Actions.IsWindows())
- return f(installDir, env, true);
-
- // The CLR tracer is only compatible on .NET Core >= 3 on Linux and macOS (see
- // https://github.com/dotnet/coreclr/issues/19622)
- return BuildScript.Bind(GetInstalledRuntimesScript(builder.Actions, installDir, env), (runtimes, runtimesRet) =>
- {
- var compatibleClr = false;
- if (runtimesRet == 0)
- {
- var minimumVersion = new Version(3, 0);
- var regex = new Regex(@"Microsoft\.NETCore\.App (\d\.\d\.\d)");
- compatibleClr = runtimes
- .Select(runtime => regex.Match(runtime))
- .Where(m => m.Success)
- .Select(m => m.Groups[1].Value)
- .Any(m => Version.TryParse(m, out var v) && v >= minimumVersion);
- }
-
- if (!compatibleClr)
- {
- if (env is null)
- env = new Dictionary();
- env.Add("UseSharedCompilation", "false");
- }
-
- return f(installDir, env, compatibleClr);
- });
+ if (env is null)
+ env = new Dictionary();
+ env.Add("UseSharedCompilation", "false");
+ return f(installDir, env);
});
}
@@ -122,7 +97,7 @@ namespace Semmle.Autobuild.CSharp
/// are needed).
///
public static BuildScript WithDotNet(Autobuilder builder, Func?, BuildScript> f)
- => WithDotNet(builder, (_1, env, _2) => f(env));
+ => WithDotNet(builder, (_1, env) => f(env));
///
/// Returns a script for downloading relevant versions of the
@@ -259,14 +234,6 @@ namespace Semmle.Autobuild.CSharp
return restore;
}
- private static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string? dotNetPath, IDictionary? environment)
- {
- var listSdks = new CommandBuilder(actions, environment: environment, silent: true).
- RunCommand(DotNetCommand(actions, dotNetPath)).
- Argument("--list-runtimes");
- return listSdks.Script;
- }
-
///
/// Gets the `dotnet build` script.
///
@@ -276,17 +243,14 @@ namespace Semmle.Autobuild.CSharp
/// hence the need for CLR tracing), by adding a
/// `/p:UseSharedCompilation=false` argument.
///
- private static BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary? environment, bool compatibleClr, string projOrSln)
+ private static BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary? environment, string projOrSln)
{
var build = new CommandBuilder(builder.Actions, null, environment);
var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, dotNetPath)).
Argument("build").
Argument("--no-incremental");
- return compatibleClr ?
- script.Argument(builder.Options.DotNetArguments).
- QuoteArgument(projOrSln).
- Script :
+ return
script.Argument("/p:UseSharedCompilation=false").
Argument(builder.Options.DotNetArguments).
QuoteArgument(projOrSln).
From bf4d88175c9727414780b04802fa0e1ed8e92e71 Mon Sep 17 00:00:00 2001
From: Sebastian Bauersfeld
Date: Wed, 12 May 2021 16:40:00 +0700
Subject: [PATCH 124/168] Consider boxed booleans to avoid false positives for
XXE.ql
---
java/ql/src/semmle/code/java/security/XmlParsers.qll | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/java/ql/src/semmle/code/java/security/XmlParsers.qll b/java/ql/src/semmle/code/java/security/XmlParsers.qll
index 685c5754fc9..5e2eb1caf8a 100644
--- a/java/ql/src/semmle/code/java/security/XmlParsers.qll
+++ b/java/ql/src/semmle/code/java/security/XmlParsers.qll
@@ -36,7 +36,10 @@ abstract class ParserConfig extends MethodAccess {
*/
predicate disables(Expr e) {
this.getArgument(0) = e and
- this.getArgument(1).(BooleanLiteral).getBooleanValue() = false
+ (
+ this.getArgument(1).(BooleanLiteral).getBooleanValue() = false or
+ this.getArgument(1).(FieldAccess).getField().hasQualifiedName("java.lang", "Boolean", "FALSE")
+ )
}
/**
@@ -44,7 +47,10 @@ abstract class ParserConfig extends MethodAccess {
*/
predicate enables(Expr e) {
this.getArgument(0) = e and
- this.getArgument(1).(BooleanLiteral).getBooleanValue() = true
+ (
+ this.getArgument(1).(BooleanLiteral).getBooleanValue() = true or
+ this.getArgument(1).(FieldAccess).getField().hasQualifiedName("java.lang", "Boolean", "TRUE")
+ )
}
}
From b05512a9585def1ecb9fd2c35cfebbcc70ab6ef8 Mon Sep 17 00:00:00 2001
From: Sebastian Bauersfeld
Date: Wed, 12 May 2021 16:58:24 +0700
Subject: [PATCH 125/168] Add change notes.
---
java/change-notes/2021-05-12-xxe-fp-fix.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 java/change-notes/2021-05-12-xxe-fp-fix.md
diff --git a/java/change-notes/2021-05-12-xxe-fp-fix.md b/java/change-notes/2021-05-12-xxe-fp-fix.md
new file mode 100644
index 00000000000..dd42bc71256
--- /dev/null
+++ b/java/change-notes/2021-05-12-xxe-fp-fix.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* The query "Resolving XML external entity in user-controlled data" (`java/xxe`) has been improved to report fewer false positives when a Builder / Factory (e.g. an `XMLInputFactory`) is configured safely by using a boxed boolean as second argument to one or more of its configuration methods.
From 48b50f93c27c60ad41ebd112f6b699ac987503fa Mon Sep 17 00:00:00 2001
From: Jonathan Leitschuh
Date: Wed, 12 May 2021 08:58:01 -0400
Subject: [PATCH 126/168] Update
java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
Co-authored-by: Tony Torralba
---
.../code/java/frameworks/jackson/JacksonSerializability.qll | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 09fd419642e..50266c377f8 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -53,7 +53,10 @@ private class JacksonWriteValueMethod extends Method, TaintPreservingCallable {
private class JacksonReadValueMethod extends Method, TaintPreservingCallable {
JacksonReadValueMethod() {
- getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") and
+ (
+ getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectReader") or
+ getDeclaringType().hasQualifiedName("com.fasterxml.jackson.databind", "ObjectMapper")
+ ) and
hasName(["readValue", "readValues"])
}
From e94dab70b50ce64f692fb6e8db93149ce063f9d5 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Wed, 12 May 2021 15:44:09 +0200
Subject: [PATCH 127/168] C++: Add sanitizers to cpp/uncontrolled-arithmetic.
---
.../CWE/CWE-190/ArithmeticUncontrolled.ql | 111 +++++++++++++-----
.../ArithmeticUncontrolled.expected | 46 --------
.../CWE/CWE-190/semmle/uncontrolled/test.c | 6 +-
3 files changed, 84 insertions(+), 79 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql
index a4b0f131d14..6aad6cca7ce 100644
--- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql
+++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql
@@ -15,34 +15,99 @@ import cpp
import semmle.code.cpp.security.Overflow
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.TaintTracking
+import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import TaintedWithPath
-predicate isRandCall(FunctionCall fc) { fc.getTarget().getName() = "rand" }
-
-predicate isRandCallOrParent(Expr e) {
- isRandCall(e) or
- isRandCallOrParent(e.getAChild())
+predicate isUnboundedRandCall(FunctionCall fc) {
+ fc.getTarget().getName() = "rand" and not bounded(fc)
}
-predicate isRandValue(Expr e) {
- isRandCall(e)
+/**
+ * An operand `e` of a division expression (i.e., `e` is an operand of either a `DivExpr` or
+ * a `AssignDivExpr`) is bounded when `e` is the left-hand side of the division.
+ */
+pragma[inline]
+predicate boundedDiv(Expr e, Expr left) { e = left }
+
+/**
+ * An operand `e` of a remainder expression `rem` (i.e., `rem` is either a `RemExpr` or
+ * an `AssignRemExpr`) with left-hand side `left` and right-ahnd side `right` is bounded
+ * when `e` is `left` and `right` is upper bounded by some number that is less than the maximum integer
+ * allowed by the result type of `rem`.
+ */
+pragma[inline]
+predicate boundedRem(Expr e, Expr rem, Expr left, Expr right) {
+ e = left and
+ upperBound(right.getFullyConverted()) < exprMaxVal(rem.getFullyConverted())
+}
+
+/**
+ * An operand `e` of a bitwise and expression `andExpr` (i.e., `andExpr` is either an `BitwiseAndExpr`
+ * or an `AssignAndExpr`) with operands `operand1` and `operand2` is the operand that is not `e` is upper
+ * bounded by some number that is less than the maximum integer allowed by the result type of `andExpr`.
+ */
+pragma[inline]
+predicate boundedBitwiseAnd(Expr e, Expr andExpr, Expr operand1, Expr operand2) {
+ operand1 != operand2 and
+ e = operand1 and
+ upperBound(operand2.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
+}
+
+/**
+ * Holds if `fc` is a part of the left operand of a binary operation that greatly reduces the range
+ * of possible values.
+ */
+predicate bounded(Expr e) {
+ // For `%` and `&` we require that `e` is bounded by a value that is strictly smaller than the
+ // maximum possible value of the result type of the operation.
+ // For example, the function call `rand()` is considered bounded in the following program:
+ // ```
+ // int i = rand() % (UINT8_MAX + 1);
+ // ```
+ // but not in:
+ // ```
+ // unsigned char uc = rand() % (UINT8_MAX + 1);
+ // ```
+ exists(RemExpr rem | boundedRem(e, rem, rem.getLeftOperand(), rem.getRightOperand()))
+ or
+ exists(AssignRemExpr rem | boundedRem(e, rem, rem.getLValue(), rem.getRValue()))
+ or
+ exists(BitwiseAndExpr andExpr |
+ boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
+ )
+ or
+ exists(AssignAndExpr andExpr |
+ boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
+ )
+ or
+ // Optimitically assume that a division always yields a much smaller value.
+ boundedDiv(e, any(DivExpr div).getLeftOperand())
+ or
+ boundedDiv(e, any(AssignDivExpr div).getLValue())
+}
+
+predicate isUnboundedRandCallOrParent(Expr e) {
+ isUnboundedRandCall(e)
+ or
+ isUnboundedRandCallOrParent(e.getAChild())
+}
+
+predicate isUnboundedRandValue(Expr e) {
+ isUnboundedRandCall(e)
or
exists(MacroInvocation mi |
e = mi.getExpr() and
- isRandCallOrParent(e)
+ isUnboundedRandCallOrParent(e)
)
}
class SecurityOptionsArith extends SecurityOptions {
override predicate isUserInput(Expr expr, string cause) {
- isRandValue(expr) and
- cause = "rand" and
- not expr.getParent*() instanceof DivExpr
+ isUnboundedRandValue(expr) and
+ cause = "rand"
}
}
-predicate isDiv(VariableAccess va) { exists(AssignDivExpr div | div.getLValue() = va) }
-
predicate missingGuard(VariableAccess va, string effect) {
exists(Operation op | op.getAnOperand() = va |
missingGuardAgainstUnderflow(op, va) and effect = "underflow"
@@ -52,29 +117,15 @@ predicate missingGuard(VariableAccess va, string effect) {
}
class Configuration extends TaintTrackingConfiguration {
- override predicate isSink(Element e) {
- isDiv(e)
- or
- missingGuard(e, _)
- }
-}
+ override predicate isSink(Element e) { missingGuard(e, _) }
-/**
- * A value that undergoes division is likely to be bounded within a safe
- * range.
- */
-predicate guardedByAssignDiv(Expr origin) {
- exists(VariableAccess va |
- taintedWithPath(origin, va, _, _) and
- isDiv(va)
- )
+ override predicate isBarrier(Expr e) { super.isBarrier(e) or bounded(e) }
}
from Expr origin, VariableAccess va, string effect, PathNode sourceNode, PathNode sinkNode
where
taintedWithPath(origin, va, sourceNode, sinkNode) and
- missingGuard(va, effect) and
- not guardedByAssignDiv(origin)
+ missingGuard(va, effect)
select va, sourceNode, sinkNode,
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin,
"Uncontrolled value"
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected
index ca8dd38fc3b..097efb73b9f 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected
@@ -7,30 +7,10 @@ edges
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
-| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r |
-| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r |
-| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r |
-| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r |
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
-| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r |
-| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r |
-| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r |
-| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r |
-| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r |
-| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r |
-| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r |
-| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r |
-| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r |
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
@@ -67,34 +47,11 @@ nodes
| test.c:35:5:35:5 | r | semmle.label | r |
| test.c:35:5:35:5 | r | semmle.label | r |
| test.c:35:5:35:5 | r | semmle.label | r |
-| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... |
-| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... |
-| test.c:40:5:40:5 | r | semmle.label | r |
-| test.c:40:5:40:5 | r | semmle.label | r |
-| test.c:40:5:40:5 | r | semmle.label | r |
| test.c:44:13:44:16 | call to rand | semmle.label | call to rand |
| test.c:44:13:44:16 | call to rand | semmle.label | call to rand |
| test.c:45:5:45:5 | r | semmle.label | r |
| test.c:45:5:45:5 | r | semmle.label | r |
| test.c:45:5:45:5 | r | semmle.label | r |
-| test.c:54:13:54:16 | call to rand | semmle.label | call to rand |
-| test.c:54:13:54:16 | call to rand | semmle.label | call to rand |
-| test.c:56:5:56:5 | r | semmle.label | r |
-| test.c:56:5:56:5 | r | semmle.label | r |
-| test.c:56:5:56:5 | r | semmle.label | r |
-| test.c:60:13:60:16 | call to rand | semmle.label | call to rand |
-| test.c:60:13:60:16 | call to rand | semmle.label | call to rand |
-| test.c:61:5:61:5 | r | semmle.label | r |
-| test.c:61:5:61:5 | r | semmle.label | r |
-| test.c:61:5:61:5 | r | semmle.label | r |
-| test.c:62:5:62:5 | r | semmle.label | r |
-| test.c:62:5:62:5 | r | semmle.label | r |
-| test.c:62:5:62:5 | r | semmle.label | r |
-| test.c:66:13:66:16 | call to rand | semmle.label | call to rand |
-| test.c:66:13:66:16 | call to rand | semmle.label | call to rand |
-| test.c:67:5:67:5 | r | semmle.label | r |
-| test.c:67:5:67:5 | r | semmle.label | r |
-| test.c:67:5:67:5 | r | semmle.label | r |
| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... |
| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... |
| test.c:77:9:77:9 | r | semmle.label | r |
@@ -133,10 +90,7 @@ nodes
#select
| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value |
| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value |
-| test.c:40:5:40:5 | r | test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value |
| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value |
-| test.c:56:5:56:5 | r | test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value |
-| test.c:67:5:67:5 | r | test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value |
| test.c:77:9:77:9 | r | test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value |
| test.c:100:5:100:5 | r | test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value |
| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c
index 2b67b499a3c..61f39a8e851 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c
@@ -37,7 +37,7 @@ void randomTester() {
{
int r = RANDN(100);
- r += 100; // GOOD: The return from RANDN is bounded [FALSE POSITIVE]
+ r += 100; // GOOD: The return from RANDN is bounded
}
{
@@ -53,7 +53,7 @@ void randomTester() {
{
int r = rand();
r = r / 10;
- r += 100; // GOOD [FALSE POSITIVE]
+ r += 100; // GOOD
}
{
@@ -64,7 +64,7 @@ void randomTester() {
{
int r = rand() & 0xFF;
- r += 100; // GOOD [FALSE POSITIVE]
+ r += 100; // GOOD
}
{
From e0f78dde56f7f31719c91cd0367922046edaa2ab Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 12 May 2021 16:23:37 +0200
Subject: [PATCH 128/168] make the axios error catch match the non-error case
---
.../ql/src/semmle/javascript/frameworks/ClientRequests.qll | 3 +--
.../frameworks/ClientRequests/ClientRequests.expected | 4 +++-
.../ql/test/library-tests/frameworks/ClientRequests/tst.js | 1 +
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
index 477f9354d03..bce5d6a36fc 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
@@ -271,8 +271,7 @@ module ClientRequest {
or
responseType = getResponseType() and
promise = false and
- result =
- getReturn().getPromisedError().getMember("response").getMember("data").getAnImmediateUse()
+ result = getReturn().getPromisedError().getMember("response").getAnImmediateUse()
}
}
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
index c6542eb009d..27a9fa10f72 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected
@@ -298,4 +298,6 @@ test_getAResponseDataNode
| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:73:235:76 | body | json | false |
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:291:44:291:53 | event.data | json | false |
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:296:5:299:6 | axios({ ... \\n }) | json | true |
-| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:303:26:303:42 | err.response.data | json | false |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:302:28:302:39 | err.response | json | false |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:303:26:303:37 | err.response | json | false |
+| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:304:27:304:38 | err.response | json | false |
diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
index f284ffaa407..40dcfc481f4 100644
--- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
+++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js
@@ -301,6 +301,7 @@ function moreAxios() {
(err) => {
const status = err.response.status;
const data = err.response.data;
+ const agent = err.response.headers.useragent;
}
);
}
\ No newline at end of file
From 7d26aca793353c8564d5cac8715dbcecd87aa917 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Wed, 12 May 2021 16:34:23 +0200
Subject: [PATCH 129/168] C++: Add change-note.
---
cpp/change-notes/2021-12-05-uncontrolled-arithmetic.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 cpp/change-notes/2021-12-05-uncontrolled-arithmetic.md
diff --git a/cpp/change-notes/2021-12-05-uncontrolled-arithmetic.md b/cpp/change-notes/2021-12-05-uncontrolled-arithmetic.md
new file mode 100644
index 00000000000..56fbc9a44ce
--- /dev/null
+++ b/cpp/change-notes/2021-12-05-uncontrolled-arithmetic.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* The query "Uncontrolled arithmetic" (`cpp/uncontrolled-arithmetic`) has been improved to produce fewer false positives.
From 34fbafafde8be89e1383b378c052cbcdcdcc7000 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 12 May 2021 22:34:44 +0200
Subject: [PATCH 130/168] remove redundant "put" case
---
.../ql/src/semmle/javascript/frameworks/ClientRequests.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
index bce5d6a36fc..18204c5b59b 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll
@@ -242,7 +242,7 @@ module ClientRequest {
method = "request" and
result = getOptionArgument(0, "data")
or
- method = ["post", "put", "put"] and
+ method = ["post", "put"] and
result = [getArgument(1), getOptionArgument(2, "data")]
or
result = getOptionArgument([0 .. 2], ["headers", "params"])
From effa2b162a77031186bf26114e2e6e0e6e847154 Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 6 May 2021 12:05:26 +0800
Subject: [PATCH 131/168] Add spring url redirection detect
---
.../CWE/CWE-601/SpringUrlRedirect.java | 46 +++++++
.../CWE/CWE-601/SpringUrlRedirect.qhelp | 37 +++++
.../Security/CWE/CWE-601/SpringUrlRedirect.ql | 42 ++++++
.../CWE/CWE-601/SpringUrlRedirect.qll | 91 ++++++++++++
.../CWE-601/SpringUrlRedirect.expected | 19 +++
.../security/CWE-601/SpringUrlRedirect.java | 52 +++++++
.../security/CWE-601/SpringUrlRedirect.qlref | 1 +
.../query-tests/security/CWE-601/options | 1 +
.../web/servlet/ModelAndView.java | 107 +++++++++++++++
.../org/springframework/web/servlet/View.java | 20 +++
.../servlet/view/AbstractUrlBasedView.java | 39 ++++++
.../web/servlet/view/RedirectView.java | 129 ++++++++++++++++++
12 files changed, 584 insertions(+)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.qlref
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-601/options
create mode 100644 java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/ModelAndView.java
create mode 100644 java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/View.java
create mode 100644 java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/AbstractUrlBasedView.java
create mode 100644 java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/RedirectView.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.java b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.java
new file mode 100644
index 00000000000..eba64aab6a8
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.java
@@ -0,0 +1,46 @@
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.view.RedirectView;
+
+@Controller
+public class SpringUrlRedirect {
+
+ private final static String VALID_REDIRECT = "http://127.0.0.1";
+
+ @GetMapping("url1")
+ public RedirectView bad1(String redirectUrl, HttpServletResponse response) throws Exception {
+ RedirectView rv = new RedirectView();
+ rv.setUrl(redirectUrl);
+ return rv;
+ }
+
+ @GetMapping("url2")
+ public String bad2(String redirectUrl) {
+ String url = "redirect:" + redirectUrl;
+ return url;
+ }
+
+ @GetMapping("url3")
+ public RedirectView bad3(String redirectUrl) {
+ RedirectView rv = new RedirectView(redirectUrl);
+ return rv;
+ }
+
+ @GetMapping("url4")
+ public ModelAndView bad4(String redirectUrl) {
+ return new ModelAndView("redirect:" + redirectUrl);
+ }
+
+ @GetMapping("url5")
+ public RedirectView good1(String redirectUrl) {
+ RedirectView rv = new RedirectView();
+ if (redirectUrl.startsWith(VALID_REDIRECT)){
+ rv.setUrl(redirectUrl);
+ }else {
+ rv.setUrl(VALID_REDIRECT);
+ }
+ return rv;
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qhelp b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qhelp
new file mode 100644
index 00000000000..6fe70dfb113
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qhelp
@@ -0,0 +1,37 @@
+
+
+
+
+
+
Directly incorporating user input into a URL redirect request without validating the input
+can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a
+malicious site that looks very similar to the real site they intend to visit, but which is
+controlled by the attacker.
+
+
+
+
+
To guard against untrusted URL redirection, it is advisable to avoid putting user input
+directly into a redirect URL. Instead, maintain a list of authorized
+redirects on the server; then choose from that list based on the user input provided.
+
+
+
+
+
The following examples show the bad case and the good case respectively.
+In bad1 method and bad2 method and bad3 method and
+bad4 method, shows an HTTP request parameter being used directly in a URL redirect
+without validating the input, which facilitates phishing attacks. In good1 method,
+shows how to solve this problem by verifying whether the user input is a known fixed string beginning.
+
+
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
new file mode 100644
index 00000000000..138bce57ac9
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
@@ -0,0 +1,42 @@
+/**
+ * @name Spring url redirection from remote source
+ * @description Spring url redirection based on unvalidated user-input
+ * may cause redirection to malicious web sites.
+ * @kind path-problem
+ * @problem.severity error
+ * @precision high
+ * @id java/spring-unvalidated-url-redirection
+ * @tags security
+ * external/cwe-601
+ */
+
+import java
+import SpringUrlRedirect
+import semmle.code.java.dataflow.FlowSources
+import DataFlow::PathGraph
+
+class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
+ SpringUrlRedirectFlowConfig() { this = "SpringUrlRedirectFlowConfig" }
+
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof SpringUrlRedirectSink }
+
+ override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
+ guard instanceof StartsWithSanitizer
+ }
+
+ override predicate isSanitizer(DataFlow::Node node) {
+ // Exclude the case where the left side of the concatenated string is not `redirect:`.
+ // E.g: `String url = "/path?token=" + request.getParameter("token");`
+ exists(AddExpr ae |
+ ae.getRightOperand() = node.asExpr() and
+ not ae instanceof RedirectBuilderExpr
+ )
+ }
+}
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, SpringUrlRedirectFlowConfig conf
+where conf.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "Potentially untrusted URL redirection due to $@.",
+ source.getNode(), "user-provided value"
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
new file mode 100644
index 00000000000..0ea88e84673
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -0,0 +1,91 @@
+import java
+import DataFlow
+import semmle.code.java.dataflow.FlowSources
+import semmle.code.java.dataflow.DataFlow2
+import semmle.code.java.dataflow.TaintTracking
+import semmle.code.java.frameworks.spring.SpringController
+
+class StartsWithSanitizer extends DataFlow::BarrierGuard {
+ StartsWithSanitizer() {
+ this.(MethodAccess).getMethod().hasName("startsWith") and
+ this.(MethodAccess).getMethod().getDeclaringType() instanceof TypeString and
+ this.(MethodAccess).getMethod().getNumberOfParameters() = 1
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and branch = true
+ }
+}
+
+/**
+ * A concatenate expression using the string `redirect:` on the left.
+ *
+ * E.g: `"redirect:" + redirectUrl`
+ */
+class RedirectBuilderExpr extends AddExpr {
+ RedirectBuilderExpr() {
+ this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "redirect:"
+ }
+}
+
+/** A URL redirection sink from spring controller method. */
+class SpringUrlRedirectSink extends DataFlow::Node {
+ SpringUrlRedirectSink() {
+ exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = this.asExpr())
+ or
+ exists(MethodAccess ma |
+ ma.getMethod().hasName("setUrl") and
+ ma.getMethod()
+ .getDeclaringType()
+ .hasQualifiedName("org.springframework.web.servlet.view", "AbstractUrlBasedView") and
+ ma.getArgument(0) = this.asExpr() and
+ exists(RedirectViewFlowConfig rvfc | rvfc.hasFlowToExpr(ma.getQualifier()))
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructedType()
+ .hasQualifiedName("org.springframework.web.servlet.view", "RedirectView") and
+ cie.getArgument(0) = this.asExpr()
+ )
+ or
+ exists(ClassInstanceExpr cie |
+ cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and
+ cie.getArgument(0) = this.asExpr() and
+ exists(RedirectBuilderFlowConfig rstrbfc | rstrbfc.hasFlowToExpr(cie.getArgument(0)))
+ )
+ }
+}
+
+/** A data flow configuration tracing flow from remote sources to redirect builder expression. */
+private class RedirectBuilderFlowConfig extends DataFlow2::Configuration {
+ RedirectBuilderFlowConfig() { this = "RedirectBuilderFlowConfig" }
+
+ override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = sink.asExpr())
+ }
+}
+
+/** A data flow configuration tracing flow from RedirectView object to calling setUrl method. */
+private class RedirectViewFlowConfig extends DataFlow2::Configuration {
+ RedirectViewFlowConfig() { this = "RedirectViewFlowConfig" }
+
+ override predicate isSource(DataFlow::Node src) {
+ exists(ClassInstanceExpr cie |
+ cie.getConstructedType()
+ .hasQualifiedName("org.springframework.web.servlet.view", "RedirectView") and
+ cie = src.asExpr()
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(MethodAccess ma |
+ ma.getMethod().hasName("setUrl") and
+ ma.getMethod()
+ .getDeclaringType()
+ .hasQualifiedName("org.springframework.web.servlet.view", "AbstractUrlBasedView") and
+ ma.getQualifier() = sink.asExpr()
+ )
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
new file mode 100644
index 00000000000..fee0598bbee
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
@@ -0,0 +1,19 @@
+edges
+| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl |
+| SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl |
+| SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl |
+| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl |
+nodes
+| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | semmle.label | redirectUrl |
+#select
+| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:13:30:13:47 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:20:24:20:41 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:26:30:26:47 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:32:30:32:47 | redirectUrl | user-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
new file mode 100644
index 00000000000..1438b0a63a1
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
@@ -0,0 +1,52 @@
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.view.RedirectView;
+
+@Controller
+public class SpringUrlRedirect {
+
+ private final static String VALID_REDIRECT = "http://127.0.0.1";
+
+ @GetMapping("url1")
+ public RedirectView bad1(String redirectUrl, HttpServletResponse response) throws Exception {
+ RedirectView rv = new RedirectView();
+ rv.setUrl(redirectUrl);
+ return rv;
+ }
+
+ @GetMapping("url2")
+ public String bad2(String redirectUrl) {
+ String url = "redirect:" + redirectUrl;
+ return url;
+ }
+
+ @GetMapping("url3")
+ public RedirectView bad3(String redirectUrl) {
+ RedirectView rv = new RedirectView(redirectUrl);
+ return rv;
+ }
+
+ @GetMapping("url4")
+ public ModelAndView bad4(String redirectUrl) {
+ return new ModelAndView("redirect:" + redirectUrl);
+ }
+
+ @GetMapping("url5")
+ public RedirectView good1(String redirectUrl) {
+ RedirectView rv = new RedirectView();
+ if (redirectUrl.startsWith(VALID_REDIRECT)){
+ rv.setUrl(redirectUrl);
+ }else {
+ rv.setUrl(VALID_REDIRECT);
+ }
+ return rv;
+ }
+
+ @GetMapping("url6")
+ public ModelAndView good2(String token) {
+ String url = "/edit?token=" + token;
+ return new ModelAndView("redirect:" + url);
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.qlref b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.qlref
new file mode 100644
index 00000000000..418be1d307b
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/options b/java/ql/test/experimental/query-tests/security/CWE-601/options
new file mode 100644
index 00000000000..a9289108747
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/options
@@ -0,0 +1 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/springframework-5.2.3/
\ No newline at end of file
diff --git a/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/ModelAndView.java b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/ModelAndView.java
new file mode 100644
index 00000000000..53e337d5053
--- /dev/null
+++ b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/ModelAndView.java
@@ -0,0 +1,107 @@
+package org.springframework.web.servlet;
+
+import java.util.Map;
+import org.springframework.http.HttpStatus;
+import org.springframework.lang.Nullable;
+
+public class ModelAndView {
+ @Nullable
+ private Object view;
+ @Nullable
+ private HttpStatus status;
+ private boolean cleared = false;
+
+ public ModelAndView() {
+ }
+
+ public ModelAndView(String viewName) {
+ this.view = viewName;
+ }
+
+ public ModelAndView(View view) {
+ this.view = view;
+ }
+
+ public ModelAndView(String viewName, @Nullable Map model) { }
+
+ public ModelAndView(View view, @Nullable Map model) { }
+
+ public ModelAndView(String viewName, HttpStatus status) { }
+
+ public ModelAndView(@Nullable String viewName, @Nullable Map model, @Nullable HttpStatus status) { }
+
+ public ModelAndView(String viewName, String modelName, Object modelObject) { }
+
+ public ModelAndView(View view, String modelName, Object modelObject) { }
+
+ public void setViewName(@Nullable String viewName) {
+ this.view = viewName;
+ }
+
+ @Nullable
+ public String getViewName() {
+ return "";
+ }
+
+ public void setView(@Nullable View view) { }
+
+ @Nullable
+ public View getView() {
+ return null;
+ }
+
+ public boolean hasView() {
+ return true;
+ }
+
+ public boolean isReference() {
+ return true;
+ }
+
+ @Nullable
+ protected Map getModelInternal() {
+ return null;
+ }
+
+ public Map getModel() {
+ return null;
+ }
+
+ public void setStatus(@Nullable HttpStatus status) { }
+
+ @Nullable
+ public HttpStatus getStatus() {
+ return this.status;
+ }
+
+ public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
+ return null;
+ }
+
+ public ModelAndView addObject(Object attributeValue) {
+ return null;
+ }
+
+ public ModelAndView addAllObjects(@Nullable Map modelMap) {
+ return null;
+ }
+
+ public void clear() { }
+
+ public boolean isEmpty() {
+ return true;
+ }
+
+ public boolean wasCleared() {
+ return true;
+ }
+
+ public String toString() {
+ return "";
+ }
+
+ private String formatView() {
+ return "";
+ }
+}
+
diff --git a/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/View.java b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/View.java
new file mode 100644
index 00000000000..b2281b8c250
--- /dev/null
+++ b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/View.java
@@ -0,0 +1,20 @@
+package org.springframework.web.servlet;
+
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.lang.Nullable;
+
+public interface View {
+ String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
+ String PATH_VARIABLES = View.class.getName() + ".pathVariables";
+ String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
+
+ @Nullable
+ default String getContentType() {
+ return null;
+ }
+
+ void render(@Nullable Map var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
+}
+
diff --git a/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/AbstractUrlBasedView.java b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/AbstractUrlBasedView.java
new file mode 100644
index 00000000000..9efd87af12f
--- /dev/null
+++ b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/AbstractUrlBasedView.java
@@ -0,0 +1,39 @@
+package org.springframework.web.servlet.view;
+
+import java.util.Locale;
+import org.springframework.lang.Nullable;
+
+public abstract class AbstractUrlBasedView {
+ @Nullable
+ private String url;
+
+ protected AbstractUrlBasedView() { }
+
+ protected AbstractUrlBasedView(String url) {
+ this.url = url;
+ }
+
+ public void setUrl(@Nullable String url) {
+ this.url = url;
+ }
+
+ @Nullable
+ public String getUrl() {
+ return "";
+ }
+
+ public void afterPropertiesSet() throws Exception { }
+
+ protected boolean isUrlRequired() {
+ return true;
+ }
+
+ public boolean checkResource(Locale locale) throws Exception {
+ return true;
+ }
+
+ public String toString() {
+ return "";
+ }
+}
+
diff --git a/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/RedirectView.java b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/RedirectView.java
new file mode 100644
index 00000000000..ee18868231a
--- /dev/null
+++ b/java/ql/test/stubs/springframework-5.2.3/org/springframework/web/servlet/view/RedirectView.java
@@ -0,0 +1,129 @@
+package org.springframework.web.servlet.view;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Array;
+import java.net.URLEncoder;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.http.HttpStatus;
+import org.springframework.lang.Nullable;
+
+public class RedirectView extends AbstractUrlBasedView {
+ private static final Pattern URI_TEMPLATE_VARIABLE_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
+ private boolean contextRelative = false;
+ private boolean http10Compatible = true;
+ private boolean exposeModelAttributes = true;
+ @Nullable
+ private String encodingScheme;
+ @Nullable
+ private HttpStatus statusCode;
+ private boolean expandUriTemplateVariables = true;
+ private boolean propagateQueryParams = false;
+ @Nullable
+ private String[] hosts;
+
+ public RedirectView() { }
+
+ public RedirectView(String url) { }
+
+ public RedirectView(String url, boolean contextRelative) { }
+
+ public RedirectView(String url, boolean contextRelative, boolean http10Compatible) { }
+
+ public RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes) { }
+
+ public void setContextRelative(boolean contextRelative) { }
+
+ public void setHttp10Compatible(boolean http10Compatible) { }
+
+ public void setExposeModelAttributes(boolean exposeModelAttributes) { }
+
+ public void setEncodingScheme(String encodingScheme) { }
+
+ public void setStatusCode(HttpStatus statusCode) { }
+
+ public void setExpandUriTemplateVariables(boolean expandUriTemplateVariables) { }
+
+ public void setPropagateQueryParams(boolean propagateQueryParams) { }
+
+ public boolean isPropagateQueryProperties() {
+ return true;
+ }
+
+ public void setHosts(@Nullable String... hosts) { }
+
+ @Nullable
+ public String[] getHosts() {
+ return this.hosts;
+ }
+
+ public boolean isRedirectView() {
+ return true;
+ }
+
+ protected boolean isContextRequired() {
+ return false;
+ }
+
+ protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws IOException { }
+
+ protected final String createTargetUrl(Map model, HttpServletRequest request) throws UnsupportedEncodingException {
+ return "";
+ }
+
+ private String getContextPath(HttpServletRequest request) {
+ return "";
+ }
+
+ protected StringBuilder replaceUriTemplateVariables(String targetUrl, Map model, Map currentUriVariables, String encodingScheme) throws UnsupportedEncodingException {
+ return null;
+ }
+
+ private Map getCurrentRequestUriVariables(HttpServletRequest request) {
+ return null;
+ }
+
+ protected void appendCurrentQueryParams(StringBuilder targetUrl, HttpServletRequest request) { }
+
+ protected void appendQueryProperties(StringBuilder targetUrl, Map model, String encodingScheme) throws UnsupportedEncodingException { }
+
+ protected Map queryProperties(Map model) {
+ return null;
+ }
+
+ protected boolean isEligibleProperty(String key, @Nullable Object value) {
+ return true;
+ }
+
+ protected boolean isEligibleValue(@Nullable Object value) {
+ return true;
+ }
+
+ protected String urlEncode(String input, String encodingScheme) throws UnsupportedEncodingException {
+ return "";
+ }
+
+ protected String updateTargetUrl(String targetUrl, Map model, HttpServletRequest request, HttpServletResponse response) {
+ return "";
+ }
+
+ protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl, boolean http10Compatible) throws IOException { }
+
+ protected boolean isRemoteHost(String targetUrl) {
+ return true;
+ }
+
+ protected HttpStatus getHttp11StatusCode(HttpServletRequest request, HttpServletResponse response, String targetUrl) {
+ return this.statusCode;
+ }
+}
+
From 02e415045f04957a33049907bd3256ce84ad7378 Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 13 May 2021 15:48:15 +0800
Subject: [PATCH 132/168] Delete RedirectBuilderFlowConfig
---
.../Security/CWE/CWE-601/SpringUrlRedirect.qll | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
index 0ea88e84673..1ab5f3cd0b1 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -51,22 +51,11 @@ class SpringUrlRedirectSink extends DataFlow::Node {
exists(ClassInstanceExpr cie |
cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and
cie.getArgument(0) = this.asExpr() and
- exists(RedirectBuilderFlowConfig rstrbfc | rstrbfc.hasFlowToExpr(cie.getArgument(0)))
+ exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = this.asExpr())
)
}
}
-/** A data flow configuration tracing flow from remote sources to redirect builder expression. */
-private class RedirectBuilderFlowConfig extends DataFlow2::Configuration {
- RedirectBuilderFlowConfig() { this = "RedirectBuilderFlowConfig" }
-
- override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
-
- override predicate isSink(DataFlow::Node sink) {
- exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = sink.asExpr())
- }
-}
-
/** A data flow configuration tracing flow from RedirectView object to calling setUrl method. */
private class RedirectViewFlowConfig extends DataFlow2::Configuration {
RedirectViewFlowConfig() { this = "RedirectViewFlowConfig" }
From 51067af784f47fccb040a6d99ac16491b6a58cf6 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Thu, 13 May 2021 22:34:10 +0200
Subject: [PATCH 133/168] add "uid" (and friends) as maybe being sensitive
account info
---
.../internal/SensitiveDataHeuristics.qll | 3 +-
.../CWE-338/InsecureRandomness.expected | 40 +++++++++++++++++++
.../test/query-tests/Security/CWE-338/tst.js | 9 ++++-
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll b/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
index ddf95b1b534..9a3a306c159 100644
--- a/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
+++ b/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
@@ -58,7 +58,8 @@ module HeuristicNames {
*/
string maybeAccountInfo() {
result = "(?is).*acc(ou)?nt.*" or
- result = "(?is).*(puid|username|userid).*"
+ result = "(?is).*(puid|username|userid).*" or
+ result = "(?is).*(u|^|_|[a-z(?=U)])(uid).*"
}
/**
diff --git a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
index e4ab385cc07..4db1bb3b088 100644
--- a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
@@ -66,6 +66,26 @@ nodes
| tst.js:95:33:95:45 | Math.random() |
| tst.js:95:33:95:45 | Math.random() |
| tst.js:95:33:95:45 | Math.random() |
+| tst.js:115:16:115:56 | Math.fl ... 00_000) |
+| tst.js:115:16:115:56 | Math.fl ... 00_000) |
+| tst.js:115:27:115:39 | Math.random() |
+| tst.js:115:27:115:39 | Math.random() |
+| tst.js:115:27:115:55 | Math.ra ... 000_000 |
+| tst.js:116:22:116:62 | Math.fl ... 00_000) |
+| tst.js:116:22:116:62 | Math.fl ... 00_000) |
+| tst.js:116:33:116:45 | Math.random() |
+| tst.js:116:33:116:45 | Math.random() |
+| tst.js:116:33:116:61 | Math.ra ... 000_000 |
+| tst.js:117:15:117:55 | Math.fl ... 00_000) |
+| tst.js:117:15:117:55 | Math.fl ... 00_000) |
+| tst.js:117:26:117:38 | Math.random() |
+| tst.js:117:26:117:38 | Math.random() |
+| tst.js:117:26:117:54 | Math.ra ... 000_000 |
+| tst.js:118:23:118:63 | Math.fl ... 00_000) |
+| tst.js:118:23:118:63 | Math.fl ... 00_000) |
+| tst.js:118:34:118:46 | Math.random() |
+| tst.js:118:34:118:46 | Math.random() |
+| tst.js:118:34:118:62 | Math.ra ... 000_000 |
edges
| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() |
| tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() |
@@ -114,6 +134,22 @@ edges
| tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() |
| tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() |
| tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() |
+| tst.js:115:27:115:39 | Math.random() | tst.js:115:27:115:55 | Math.ra ... 000_000 |
+| tst.js:115:27:115:39 | Math.random() | tst.js:115:27:115:55 | Math.ra ... 000_000 |
+| tst.js:115:27:115:55 | Math.ra ... 000_000 | tst.js:115:16:115:56 | Math.fl ... 00_000) |
+| tst.js:115:27:115:55 | Math.ra ... 000_000 | tst.js:115:16:115:56 | Math.fl ... 00_000) |
+| tst.js:116:33:116:45 | Math.random() | tst.js:116:33:116:61 | Math.ra ... 000_000 |
+| tst.js:116:33:116:45 | Math.random() | tst.js:116:33:116:61 | Math.ra ... 000_000 |
+| tst.js:116:33:116:61 | Math.ra ... 000_000 | tst.js:116:22:116:62 | Math.fl ... 00_000) |
+| tst.js:116:33:116:61 | Math.ra ... 000_000 | tst.js:116:22:116:62 | Math.fl ... 00_000) |
+| tst.js:117:26:117:38 | Math.random() | tst.js:117:26:117:54 | Math.ra ... 000_000 |
+| tst.js:117:26:117:38 | Math.random() | tst.js:117:26:117:54 | Math.ra ... 000_000 |
+| tst.js:117:26:117:54 | Math.ra ... 000_000 | tst.js:117:15:117:55 | Math.fl ... 00_000) |
+| tst.js:117:26:117:54 | Math.ra ... 000_000 | tst.js:117:15:117:55 | Math.fl ... 00_000) |
+| tst.js:118:34:118:46 | Math.random() | tst.js:118:34:118:62 | Math.ra ... 000_000 |
+| tst.js:118:34:118:46 | Math.random() | tst.js:118:34:118:62 | Math.ra ... 000_000 |
+| tst.js:118:34:118:62 | Math.ra ... 000_000 | tst.js:118:23:118:63 | Math.fl ... 00_000) |
+| tst.js:118:34:118:62 | Math.ra ... 000_000 | tst.js:118:23:118:63 | Math.fl ... 00_000) |
#select
| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:2:20:2:32 | Math.random() | random value |
| tst.js:6:20:6:43 | "prefix ... andom() | tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure $@ in a security context. | tst.js:6:31:6:43 | Math.random() | random value |
@@ -131,3 +167,7 @@ edges
| tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:84:19:84:31 | Math.random() | random value |
| tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:90:32:90:44 | Math.random() | random value |
| tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:95:33:95:45 | Math.random() | random value |
+| tst.js:115:16:115:56 | Math.fl ... 00_000) | tst.js:115:27:115:39 | Math.random() | tst.js:115:16:115:56 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:115:27:115:39 | Math.random() | random value |
+| tst.js:116:22:116:62 | Math.fl ... 00_000) | tst.js:116:33:116:45 | Math.random() | tst.js:116:22:116:62 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:116:33:116:45 | Math.random() | random value |
+| tst.js:117:15:117:55 | Math.fl ... 00_000) | tst.js:117:26:117:38 | Math.random() | tst.js:117:15:117:55 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:117:26:117:38 | Math.random() | random value |
+| tst.js:118:23:118:63 | Math.fl ... 00_000) | tst.js:118:34:118:46 | Math.random() | tst.js:118:23:118:63 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:118:34:118:46 | Math.random() | random value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-338/tst.js b/javascript/ql/test/query-tests/Security/CWE-338/tst.js
index 123799426b5..6a1abf1403c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-338/tst.js
+++ b/javascript/ql/test/query-tests/Security/CWE-338/tst.js
@@ -109,4 +109,11 @@ function f18() {
}
};
var secret = genRandom(); // OK - Math.random() is only a fallback.
-})();
\ No newline at end of file
+})();
+
+function uid() {
+ var uuid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
+ var sessionUid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
+ var uid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
+ var my_nice_uid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
+}
\ No newline at end of file
From 662e335424a7205100388feaa263db724a850191 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Thu, 13 May 2021 22:54:39 +0200
Subject: [PATCH 134/168] keep python in sync
---
.../python/security/internal/SensitiveDataHeuristics.qll | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll b/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
index ddf95b1b534..9a3a306c159 100644
--- a/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
+++ b/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
@@ -58,7 +58,8 @@ module HeuristicNames {
*/
string maybeAccountInfo() {
result = "(?is).*acc(ou)?nt.*" or
- result = "(?is).*(puid|username|userid).*"
+ result = "(?is).*(puid|username|userid).*" or
+ result = "(?is).*(u|^|_|[a-z(?=U)])(uid).*"
}
/**
From 9d60ec035f991655e7ea4ead67552ec567df64c2 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Thu, 13 May 2021 23:04:30 +0200
Subject: [PATCH 135/168] fix casing on the uid regexp
---
.../security/internal/SensitiveDataHeuristics.qll | 2 +-
.../Security/CWE-338/InsecureRandomness.expected | 10 ++++++++++
javascript/ql/test/query-tests/Security/CWE-338/tst.js | 3 +++
.../security/internal/SensitiveDataHeuristics.qll | 2 +-
4 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll b/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
index 9a3a306c159..589c37120b9 100644
--- a/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
+++ b/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll
@@ -59,7 +59,7 @@ module HeuristicNames {
string maybeAccountInfo() {
result = "(?is).*acc(ou)?nt.*" or
result = "(?is).*(puid|username|userid).*" or
- result = "(?is).*(u|^|_|[a-z(?=U)])(uid).*"
+ result = "(?s).*([uU]|^|_|[a-z](?=U))([uU][iI][dD]).*"
}
/**
diff --git a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
index 4db1bb3b088..42da210c266 100644
--- a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
@@ -86,6 +86,12 @@ nodes
| tst.js:118:34:118:46 | Math.random() |
| tst.js:118:34:118:46 | Math.random() |
| tst.js:118:34:118:62 | Math.ra ... 000_000 |
+| tst.js:120:16:120:28 | Math.random() |
+| tst.js:120:16:120:28 | Math.random() |
+| tst.js:120:16:120:28 | Math.random() |
+| tst.js:121:18:121:30 | Math.random() |
+| tst.js:121:18:121:30 | Math.random() |
+| tst.js:121:18:121:30 | Math.random() |
edges
| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() |
| tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() |
@@ -150,6 +156,8 @@ edges
| tst.js:118:34:118:46 | Math.random() | tst.js:118:34:118:62 | Math.ra ... 000_000 |
| tst.js:118:34:118:62 | Math.ra ... 000_000 | tst.js:118:23:118:63 | Math.fl ... 00_000) |
| tst.js:118:34:118:62 | Math.ra ... 000_000 | tst.js:118:23:118:63 | Math.fl ... 00_000) |
+| tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() |
+| tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() |
#select
| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:2:20:2:32 | Math.random() | random value |
| tst.js:6:20:6:43 | "prefix ... andom() | tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure $@ in a security context. | tst.js:6:31:6:43 | Math.random() | random value |
@@ -171,3 +179,5 @@ edges
| tst.js:116:22:116:62 | Math.fl ... 00_000) | tst.js:116:33:116:45 | Math.random() | tst.js:116:22:116:62 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:116:33:116:45 | Math.random() | random value |
| tst.js:117:15:117:55 | Math.fl ... 00_000) | tst.js:117:26:117:38 | Math.random() | tst.js:117:15:117:55 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:117:26:117:38 | Math.random() | random value |
| tst.js:118:23:118:63 | Math.fl ... 00_000) | tst.js:118:34:118:46 | Math.random() | tst.js:118:23:118:63 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:118:34:118:46 | Math.random() | random value |
+| tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:120:16:120:28 | Math.random() | random value |
+| tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:121:18:121:30 | Math.random() | random value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-338/tst.js b/javascript/ql/test/query-tests/Security/CWE-338/tst.js
index 6a1abf1403c..77393b8983c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-338/tst.js
+++ b/javascript/ql/test/query-tests/Security/CWE-338/tst.js
@@ -116,4 +116,7 @@ function uid() {
var sessionUid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
var uid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
var my_nice_uid = Math.floor(Math.random() * 4_000_000_000); // NOT OK
+ var liquid = Math.random(); // OK
+ var UUID = Math.random(); // NOT OK
+ var MY_UID = Math.random(); // NOK OK
}
\ No newline at end of file
diff --git a/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll b/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
index 9a3a306c159..589c37120b9 100644
--- a/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
+++ b/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll
@@ -59,7 +59,7 @@ module HeuristicNames {
string maybeAccountInfo() {
result = "(?is).*acc(ou)?nt.*" or
result = "(?is).*(puid|username|userid).*" or
- result = "(?is).*(u|^|_|[a-z(?=U)])(uid).*"
+ result = "(?s).*([uU]|^|_|[a-z](?=U))([uU][iI][dD]).*"
}
/**
From 406fb1e383dcf3408b43fc752bf608bdc3b68fda Mon Sep 17 00:00:00 2001
From: Ethan P <56270045+ethanpalm@users.noreply.github.com>
Date: Thu, 13 May 2021 17:29:34 -0400
Subject: [PATCH 136/168] Update with Go custom build options
---
.../codeql-cli/creating-codeql-databases.rst | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 4f7212050df..a41727e1956 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -165,13 +165,14 @@ build steps, you may need to explicitly define each step in the command line.
.. pull-quote:: Creating databases for Go
- For Go, you should always use the CodeQL autobuilder. Install the Go
- toolchain (version 1.11 or later) and, if there are dependencies, the
- appropriate dependency manager (such as `dep
+ For Go, install the Go toolchain (version 1.11 or later) and, if there
+ are dependencies, the appropriate dependency manager (such as `dep
`__).
- Do not specify any build commands, as you will override the autobuilder
- invocation, which will create an empty database.
+ The Go autobuilder attempts to automatically detect Go code in a repository,
+ and only runs build scripts in an attempt to fetch dependencies. To force
+ CodeQL to use your build script, set the environment variable
+ `CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or pass a command.
Specifying build commands
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -200,6 +201,10 @@ commands that you can specify for compiled languages.
codeql database create csharp-database --language=csharp --command='dotnet build /p:UseSharedCompilation=false /t:rebuild'
+- Go project built using a custom build script::
+
+ CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go --command='./scripts/build.sh'
+
- Java project built using Gradle::
codeql database create java-database --language=java --command='gradle clean test'
From 498c99e26ca556e466f00015a6203f3ce64a5362 Mon Sep 17 00:00:00 2001
From: haby0
Date: Fri, 14 May 2021 16:31:59 +0800
Subject: [PATCH 137/168] Add left value, Add return expression tracing flow
---
.../CWE/CWE-601/SpringUrlRedirect.qll | 70 +++++++++++++++++--
.../CWE-601/SpringUrlRedirect.expected | 8 +++
.../security/CWE-601/SpringUrlRedirect.java | 18 ++++-
3 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
index 1ab5f3cd0b1..866eaae1c34 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -18,20 +18,48 @@ class StartsWithSanitizer extends DataFlow::BarrierGuard {
}
/**
- * A concatenate expression using the string `redirect:` on the left.
+ * A concatenate expression using the string `redirect:` or `ajaxredirect:` or `forward:` on the left.
*
* E.g: `"redirect:" + redirectUrl`
*/
class RedirectBuilderExpr extends AddExpr {
RedirectBuilderExpr() {
- this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() = "redirect:"
+ this.getLeftOperand().(CompileTimeConstantExpr).getStringValue() in [
+ "redirect:", "ajaxredirect:", "forward:"
+ ]
+ }
+}
+
+/**
+ * A call to `StringBuilder.append` or `StringBuffer.append` method, and the parameter value is
+ * `"redirect:"` or `"ajaxredirect:"` or `"forward:"`.
+ *
+ * E.g: `StringBuilder.append("redirect:")`
+ */
+class RedirectAppendCall extends MethodAccess {
+ RedirectAppendCall() {
+ this.getMethod().hasName("append") and
+ this.getMethod().getDeclaringType() instanceof StringBuildingType and
+ this.getArgument(0).(CompileTimeConstantExpr).getStringValue() in [
+ "redirect:", "ajaxredirect:", "forward:"
+ ]
}
}
/** A URL redirection sink from spring controller method. */
class SpringUrlRedirectSink extends DataFlow::Node {
SpringUrlRedirectSink() {
- exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = this.asExpr())
+ exists(RedirectBuilderExpr rbe |
+ rbe.getRightOperand() = this.asExpr() and
+ exists(RedirectBuilderFlowConfig rbfc | rbfc.hasFlow(exprNode(rbe), _))
+ )
+ or
+ exists(MethodAccess ma, RedirectAppendCall rac |
+ DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and
+ ma.getMethod().hasName("append") and
+ ma.getArgument(0) = this.asExpr() and
+ exists(RedirectBuilderFlowConfig rbfc | rbfc.hasFlow(exprNode(ma.getQualifier()), _))
+ )
or
exists(MethodAccess ma |
ma.getMethod().hasName("setUrl") and
@@ -50,8 +78,40 @@ class SpringUrlRedirectSink extends DataFlow::Node {
or
exists(ClassInstanceExpr cie |
cie.getConstructedType().hasQualifiedName("org.springframework.web.servlet", "ModelAndView") and
- cie.getArgument(0) = this.asExpr() and
- exists(RedirectBuilderExpr rbe | rbe.getRightOperand() = this.asExpr())
+ exists(RedirectBuilderExpr rbe |
+ rbe = cie.getArgument(0) and rbe.getRightOperand() = this.asExpr()
+ )
+ )
+ }
+}
+
+/** A data flow configuration tracing flow from redirect builder expression to spring controller method return expression. */
+private class RedirectBuilderFlowConfig extends DataFlow2::Configuration {
+ RedirectBuilderFlowConfig() { this = "RedirectBuilderFlowConfig" }
+
+ override predicate isSource(DataFlow::Node src) {
+ exists(RedirectBuilderExpr rbe | rbe = src.asExpr())
+ or
+ exists(MethodAccess ma, RedirectAppendCall rac |
+ DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and
+ ma.getMethod().hasName("append") and
+ ma.getQualifier() = src.asExpr()
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(ReturnStmt rs, SpringRequestMappingMethod sqmm |
+ rs.getResult() = sink.asExpr() and
+ sqmm.getBody().getAStmt() = rs
+ )
+ }
+
+ override predicate isAdditionalFlowStep(Node prod, Node succ) {
+ exists(MethodAccess ma |
+ ma.getMethod().hasName("toString") and
+ ma.getMethod().getDeclaringType() instanceof StringBuildingType and
+ ma.getQualifier() = prod.asExpr() and
+ ma = succ.asExpr()
)
}
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
index fee0598bbee..26b8acd7770 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
@@ -3,6 +3,8 @@ edges
| SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl |
| SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl |
| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl |
+| SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl |
+| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl |
nodes
| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | semmle.label | redirectUrl |
@@ -12,8 +14,14 @@ nodes
| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | semmle.label | redirectUrl |
#select
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:13:30:13:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:20:24:20:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:27:44:27:54 | redirectUrl | SpringUrlRedirect.java:26:30:26:47 | redirectUrl : String | SpringUrlRedirect.java:27:44:27:54 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:26:30:26:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:32:30:32:47 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:37:24:37:41 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:45:24:45:41 | redirectUrl | user-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
index 1438b0a63a1..5124d8cd8c6 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
@@ -34,6 +34,22 @@ public class SpringUrlRedirect {
}
@GetMapping("url5")
+ public String bad5(String redirectUrl) {
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append("redirect:");
+ stringBuffer.append(redirectUrl);
+ return stringBuffer.toString();
+ }
+
+ @GetMapping("url6")
+ public String bad6(String redirectUrl) {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("redirect:");
+ stringBuilder.append(redirectUrl);
+ return stringBuilder.toString();
+ }
+
+ @GetMapping("url7")
public RedirectView good1(String redirectUrl) {
RedirectView rv = new RedirectView();
if (redirectUrl.startsWith(VALID_REDIRECT)){
@@ -44,7 +60,7 @@ public class SpringUrlRedirect {
return rv;
}
- @GetMapping("url6")
+ @GetMapping("url8")
public ModelAndView good2(String token) {
String url = "/edit?token=" + token;
return new ModelAndView("redirect:" + url);
From f378513ea39f33b15879653e489653d719633910 Mon Sep 17 00:00:00 2001
From: Robin Neatherway
Date: Fri, 14 May 2021 11:19:20 +0100
Subject: [PATCH 138/168] Add lines-of-code tags
This is a proposed method for advertising which queries are measuring
the lines of code in a project in a more robust manner than inspecting
the rule id.
Note that the python "LinesOfUserCode" query should _not_ have this
property, as otherwise the results of the two queries will be summed.
---
cpp/ql/src/Summary/LinesOfCode.ql | 1 +
csharp/ql/src/Metrics/Summaries/LinesOfCode.ql | 1 +
java/ql/src/Metrics/Summaries/LinesOfCode.ql | 1 +
javascript/ql/src/Summary/LinesOfCode.ql | 1 +
python/ql/src/Summary/LinesOfCode.ql | 1 +
5 files changed, 5 insertions(+)
diff --git a/cpp/ql/src/Summary/LinesOfCode.ql b/cpp/ql/src/Summary/LinesOfCode.ql
index 3b2aa2ac4c9..2d816b349e8 100644
--- a/cpp/ql/src/Summary/LinesOfCode.ql
+++ b/cpp/ql/src/Summary/LinesOfCode.ql
@@ -4,6 +4,7 @@
* @description The total number of lines of C/C++ code across all files, including system headers, libraries, and auto-generated files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
+ * lines-of-code
*/
import cpp
diff --git a/csharp/ql/src/Metrics/Summaries/LinesOfCode.ql b/csharp/ql/src/Metrics/Summaries/LinesOfCode.ql
index 9156a5e4a7f..e93e3c7416f 100644
--- a/csharp/ql/src/Metrics/Summaries/LinesOfCode.ql
+++ b/csharp/ql/src/Metrics/Summaries/LinesOfCode.ql
@@ -4,6 +4,7 @@
* @description The total number of lines of code across all files. This is a useful metric of the size of a database. For all files that were seen during the build, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
+ * lines-of-code
*/
import csharp
diff --git a/java/ql/src/Metrics/Summaries/LinesOfCode.ql b/java/ql/src/Metrics/Summaries/LinesOfCode.ql
index d6db7c6ee6b..c622f8b08ba 100644
--- a/java/ql/src/Metrics/Summaries/LinesOfCode.ql
+++ b/java/ql/src/Metrics/Summaries/LinesOfCode.ql
@@ -6,6 +6,7 @@
* or comments.
* @kind metric
* @tags summary
+ * lines-of-code
*/
import java
diff --git a/javascript/ql/src/Summary/LinesOfCode.ql b/javascript/ql/src/Summary/LinesOfCode.ql
index 9f89e0e2163..cadf0a9cf8f 100644
--- a/javascript/ql/src/Summary/LinesOfCode.ql
+++ b/javascript/ql/src/Summary/LinesOfCode.ql
@@ -4,6 +4,7 @@
* @description The total number of lines of JavaScript or TypeScript code across all files checked into the repository, except in `node_modules`. This is a useful metric of the size of a database. For all files that were seen during extraction, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
+ * lines-of-code
*/
import javascript
diff --git a/python/ql/src/Summary/LinesOfCode.ql b/python/ql/src/Summary/LinesOfCode.ql
index d9bfc4f872c..ad0b77730de 100644
--- a/python/ql/src/Summary/LinesOfCode.ql
+++ b/python/ql/src/Summary/LinesOfCode.ql
@@ -5,6 +5,7 @@
* database. This query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
+ * lines-of-code
* @id py/summary/lines-of-code
*/
From 5031b73f3509e4d1c1ce21586dd1262502177670 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 14 May 2021 13:43:20 +0200
Subject: [PATCH 139/168] C++: Add barrier to cpp/uncontrolled-allocation-size
that blocks flow when overflow isn't possible.
---
.../CWE/CWE-190/TaintedAllocationSize.ql | 16 ++++++++++
.../TaintedAllocationSize.expected | 30 -------------------
.../semmle/TaintedAllocationSize/test.cpp | 6 ++--
3 files changed, 19 insertions(+), 33 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
index cc2d52385c7..859d56ec2a0 100644
--- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
+++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
@@ -12,6 +12,7 @@
*/
import cpp
+import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.security.TaintTracking
import TaintedWithPath
@@ -27,6 +28,21 @@ predicate allocSink(Expr alloc, Expr tainted) {
class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration {
override predicate isSink(Element tainted) { allocSink(_, tainted) }
+
+ override predicate isBarrier(Expr e) {
+ super.isBarrier(e)
+ or
+ // There can be two separate reasons for `convertedExprMightOverflow` not holding:
+ // 1. `e` really cannot overflow.
+ // 2. `e` isn't analyzable.
+ // If we didn't rule out case 2 we would place barriers on anything that isn't analyzable.
+ (
+ e instanceof UnaryArithmeticOperation or
+ e instanceof BinaryArithmeticOperation or
+ e instanceof AssignArithmeticOperation
+ ) and
+ not convertedExprMightOverflow(e)
+ }
}
predicate taintedAllocSize(
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
index 25ff3162973..cdcf3aa6847 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
@@ -53,10 +53,6 @@ edges
| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... |
| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... |
| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... |
-| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... |
-| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... |
-| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... |
-| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... |
| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size |
| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size |
| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store |
@@ -91,14 +87,6 @@ edges
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi |
-| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
-| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
-| test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... |
-| test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... |
-| test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... |
-| test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... |
-| test.cpp:309:19:309:32 | (const char *)... | test.cpp:314:10:314:27 | ... * ... |
-| test.cpp:309:19:309:32 | (const char *)... | test.cpp:314:10:314:27 | ... * ... |
nodes
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
@@ -149,11 +137,6 @@ nodes
| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:138:19:138:24 | call to getenv | semmle.label | call to getenv |
-| test.cpp:138:19:138:32 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:201:9:201:42 | Store | semmle.label | Store |
| test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv |
| test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... |
@@ -196,16 +179,6 @@ nodes
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:301:19:301:24 | call to getenv | semmle.label | call to getenv |
-| test.cpp:301:19:301:32 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:309:19:309:24 | call to getenv | semmle.label | call to getenv |
-| test.cpp:309:19:309:32 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
#select
| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
@@ -216,7 +189,6 @@ nodes
| test.cpp:79:9:79:29 | new[] | test.cpp:97:18:97:23 | buffer | test.cpp:79:18:79:28 | ... - ... | This allocation size is derived from $@ and might overflow | test.cpp:97:18:97:23 | buffer | user input (fread) |
| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) |
| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) |
-| test.cpp:142:4:142:9 | call to malloc | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) |
| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
@@ -224,5 +196,3 @@ nodes
| test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (getenv) |
| test.cpp:281:4:281:9 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:281:11:281:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
| test.cpp:298:3:298:8 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:298:10:298:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
-| test.cpp:305:4:305:9 | call to malloc | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:301:19:301:24 | call to getenv | user input (getenv) |
-| test.cpp:314:3:314:8 | call to malloc | test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:309:19:309:24 | call to getenv | user input (getenv) |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
index 943bc3b1214..d00dc10a445 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
@@ -139,7 +139,7 @@ void more_bounded_tests() {
if (size > 0)
{
- malloc(size * sizeof(int)); // BAD
+ malloc(size * sizeof(int)); // GOOD (overflow not possible)
}
}
@@ -302,7 +302,7 @@ void equality_cases() {
if ((size == 50) || (size == 100))
{
- malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE]
+ malloc(size * sizeof(int)); // GOOD
}
}
{
@@ -311,6 +311,6 @@ void equality_cases() {
if (size != 50 && size != 100)
return;
- malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE]
+ malloc(size * sizeof(int)); // GOOD
}
}
From 1497fba6f249c757d0a37d832c49d712e879af34 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 14 May 2021 11:43:49 +0000
Subject: [PATCH 140/168] Remove the isAdditionalTaintStep predicate
---
.../Security/CWE/CWE-094/JythonInjection.ql | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
index 9991c0901dc..0f23edc69f4 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
@@ -102,16 +102,6 @@ class CodeInjectionConfiguration extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof CodeInjectionSink }
-
- override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
- // @RequestBody MyQueryObj query; interpreter.exec(query.getInterpreterCode());
- exists(MethodAccess ma |
- ma.getMethod().getDeclaringType().getASubtype*() instanceof SpringUntrustedDataType and
- not ma.getMethod().getDeclaringType() instanceof TypeObject and
- ma.getQualifier() = node1.asExpr() and
- ma = node2.asExpr()
- )
- }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, CodeInjectionConfiguration conf
From c1d41b31695edc664e2b3d8b1ca10cac3dda721b Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 14 May 2021 13:47:23 +0200
Subject: [PATCH 141/168] C++: Add false positive result from
pointer-difference expressions.
---
.../TaintedAllocationSize.expected | 14 ++++++++++++++
.../CWE-190/semmle/TaintedAllocationSize/test.cpp | 9 +++++++++
2 files changed, 23 insertions(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
index cdcf3aa6847..a96865cae60 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
@@ -87,6 +87,12 @@ edges
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | (size_t)... |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | (size_t)... |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
+| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
nodes
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
@@ -179,6 +185,13 @@ nodes
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:321:15:321:20 | call to getenv | semmle.label | call to getenv |
+| test.cpp:321:15:321:20 | call to getenv | semmle.label | call to getenv |
+| test.cpp:324:9:324:14 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:324:9:324:14 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:324:9:324:14 | offset | semmle.label | offset |
+| test.cpp:324:9:324:14 | offset | semmle.label | offset |
+| test.cpp:324:9:324:14 | offset | semmle.label | offset |
#select
| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
@@ -196,3 +209,4 @@ nodes
| test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (getenv) |
| test.cpp:281:4:281:9 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:281:11:281:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
| test.cpp:298:3:298:8 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:298:10:298:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
+| test.cpp:324:2:324:7 | call to malloc | test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset | This allocation size is derived from $@ and might overflow | test.cpp:321:15:321:20 | call to getenv | user input (getenv) |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
index d00dc10a445..0d630ac99cb 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
@@ -314,3 +314,12 @@ void equality_cases() {
malloc(size * sizeof(int)); // GOOD
}
}
+
+char * strstr(char *, const char *);
+
+void ptr_diff_case() {
+ char* user = getenv("USER");
+ char* admin_begin_pos = strstr(user, "ADMIN");
+ int offset = admin_begin_pos ? user - admin_begin_pos : 0;
+ malloc(offset); // GOOD [FALSE POSITIVE]
+}
\ No newline at end of file
From 2d0a56128d8f10acade04f99c73493671186d298 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 14 May 2021 13:49:48 +0200
Subject: [PATCH 142/168] C++: Prevent flow out of pointer-difference
expressions.
---
.../CWE/CWE-190/TaintedAllocationSize.ql | 6 +++
.../TaintedAllocationSize.expected | 48 -------------------
.../semmle/TaintedAllocationSize/test.cpp | 4 +-
3 files changed, 8 insertions(+), 50 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
index 859d56ec2a0..75cac365a1a 100644
--- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
+++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql
@@ -42,6 +42,12 @@ class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration {
e instanceof AssignArithmeticOperation
) and
not convertedExprMightOverflow(e)
+ or
+ // Subtracting two pointers is either well-defined (and the result will likely be small), or
+ // terribly undefined and dangerous. Here, we assume that the programmer has ensured that the
+ // result is well-defined (i.e., the two pointers point to the same object), and thus the result
+ // will likely be small.
+ e = any(PointerDiffExpr diff).getAnOperand()
}
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
index a96865cae60..234efe2c35b 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
@@ -27,24 +27,6 @@ edges
| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
-| test.cpp:75:25:75:29 | start | test.cpp:79:18:79:28 | ... - ... |
-| test.cpp:75:25:75:29 | start | test.cpp:79:18:79:28 | ... - ... |
-| test.cpp:75:38:75:40 | end | test.cpp:79:18:79:28 | ... - ... |
-| test.cpp:75:38:75:40 | end | test.cpp:79:18:79:28 | ... - ... |
-| test.cpp:97:18:97:23 | buffer | test.cpp:100:4:100:15 | buffer |
-| test.cpp:97:18:97:23 | buffer | test.cpp:100:17:100:22 | buffer indirection |
-| test.cpp:97:18:97:23 | buffer | test.cpp:101:4:101:15 | ... + ... |
-| test.cpp:97:18:97:23 | buffer | test.cpp:101:4:101:15 | buffer |
-| test.cpp:97:18:97:23 | fread output argument | test.cpp:100:4:100:15 | buffer |
-| test.cpp:97:18:97:23 | fread output argument | test.cpp:100:17:100:22 | buffer indirection |
-| test.cpp:97:18:97:23 | fread output argument | test.cpp:101:4:101:15 | ... + ... |
-| test.cpp:97:18:97:23 | fread output argument | test.cpp:101:4:101:15 | buffer |
-| test.cpp:100:4:100:15 | buffer | test.cpp:100:17:100:22 | processData1 output argument |
-| test.cpp:100:17:100:22 | buffer indirection | test.cpp:100:17:100:22 | processData1 output argument |
-| test.cpp:100:17:100:22 | processData1 output argument | test.cpp:101:4:101:15 | ... + ... |
-| test.cpp:100:17:100:22 | processData1 output argument | test.cpp:101:4:101:15 | buffer |
-| test.cpp:101:4:101:15 | ... + ... | test.cpp:75:38:75:40 | end |
-| test.cpp:101:4:101:15 | buffer | test.cpp:75:25:75:29 | start |
| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... |
| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... |
| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... |
@@ -87,12 +69,6 @@ edges
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | (size_t)... |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | (size_t)... |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
-| test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset |
nodes
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
@@ -118,21 +94,6 @@ nodes
| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
-| test.cpp:64:25:64:30 | *buffer | semmle.label | *buffer |
-| test.cpp:64:25:64:30 | *buffer | semmle.label | *buffer |
-| test.cpp:64:25:64:30 | buffer | semmle.label | buffer |
-| test.cpp:75:25:75:29 | start | semmle.label | start |
-| test.cpp:75:38:75:40 | end | semmle.label | end |
-| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... |
-| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... |
-| test.cpp:79:18:79:28 | ... - ... | semmle.label | ... - ... |
-| test.cpp:97:18:97:23 | buffer | semmle.label | buffer |
-| test.cpp:97:18:97:23 | fread output argument | semmle.label | fread output argument |
-| test.cpp:100:4:100:15 | buffer | semmle.label | buffer |
-| test.cpp:100:17:100:22 | buffer indirection | semmle.label | buffer indirection |
-| test.cpp:100:17:100:22 | processData1 output argument | semmle.label | processData1 output argument |
-| test.cpp:101:4:101:15 | ... + ... | semmle.label | ... + ... |
-| test.cpp:101:4:101:15 | buffer | semmle.label | buffer |
| test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:123:18:123:31 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... |
@@ -185,13 +146,6 @@ nodes
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:321:15:321:20 | call to getenv | semmle.label | call to getenv |
-| test.cpp:321:15:321:20 | call to getenv | semmle.label | call to getenv |
-| test.cpp:324:9:324:14 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:324:9:324:14 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:324:9:324:14 | offset | semmle.label | offset |
-| test.cpp:324:9:324:14 | offset | semmle.label | offset |
-| test.cpp:324:9:324:14 | offset | semmle.label | offset |
#select
| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
@@ -199,7 +153,6 @@ nodes
| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:79:9:79:29 | new[] | test.cpp:97:18:97:23 | buffer | test.cpp:79:18:79:28 | ... - ... | This allocation size is derived from $@ and might overflow | test.cpp:97:18:97:23 | buffer | user input (fread) |
| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) |
| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) |
| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
@@ -209,4 +162,3 @@ nodes
| test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (getenv) |
| test.cpp:281:4:281:9 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:281:11:281:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
| test.cpp:298:3:298:8 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:298:10:298:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
-| test.cpp:324:2:324:7 | call to malloc | test.cpp:321:15:321:20 | call to getenv | test.cpp:324:9:324:14 | offset | This allocation size is derived from $@ and might overflow | test.cpp:321:15:321:20 | call to getenv | user input (getenv) |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
index 0d630ac99cb..57eb5b91a07 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
@@ -76,7 +76,7 @@ void processData2(char *start, char *end)
{
char *copy;
- copy = new char[end - start]; // GOOD [FALSE POSITIVE]
+ copy = new char[end - start]; // GOOD
// ...
@@ -321,5 +321,5 @@ void ptr_diff_case() {
char* user = getenv("USER");
char* admin_begin_pos = strstr(user, "ADMIN");
int offset = admin_begin_pos ? user - admin_begin_pos : 0;
- malloc(offset); // GOOD [FALSE POSITIVE]
+ malloc(offset); // GOOD
}
\ No newline at end of file
From 58dde68b10d74d6d7ed4b7d206c1fe319b4e15ac Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 14 May 2021 14:16:00 +0200
Subject: [PATCH 143/168] C++: Add change-note.
---
cpp/change-notes/2021-05-14-uncontrolled-allocation-size.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 cpp/change-notes/2021-05-14-uncontrolled-allocation-size.md
diff --git a/cpp/change-notes/2021-05-14-uncontrolled-allocation-size.md b/cpp/change-notes/2021-05-14-uncontrolled-allocation-size.md
new file mode 100644
index 00000000000..6f0c9d6fa98
--- /dev/null
+++ b/cpp/change-notes/2021-05-14-uncontrolled-allocation-size.md
@@ -0,0 +1,2 @@
+lgtm
+* The "Tainted allocation size" query (cpp/uncontrolled-allocation-size) has been improved to produce fewer false positives.
From 4cf695b5ab0a8a50e5143f298e8e1ff3e7ec3c30 Mon Sep 17 00:00:00 2001
From: Ethan Palm <56270045+ethanpalm@users.noreply.github.com>
Date: Fri, 14 May 2021 10:00:17 -0400
Subject: [PATCH 144/168] specify ``--command`` option
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
---
docs/codeql/codeql-cli/creating-codeql-databases.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index a41727e1956..8810e3deb9d 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -172,7 +172,7 @@ build steps, you may need to explicitly define each step in the command line.
The Go autobuilder attempts to automatically detect Go code in a repository,
and only runs build scripts in an attempt to fetch dependencies. To force
CodeQL to use your build script, set the environment variable
- `CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or pass a command.
+ `CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or use the ``--command`` option.
Specifying build commands
~~~~~~~~~~~~~~~~~~~~~~~~~
From 6dd30ee5e2a03fdffc8b7cb8bf23689bce2813b7 Mon Sep 17 00:00:00 2001
From: Ethan Palm <56270045+ethanpalm@users.noreply.github.com>
Date: Fri, 14 May 2021 14:00:33 -0400
Subject: [PATCH 145/168] clarify options for tracing
Co-authored-by: Chris Smowton
---
docs/codeql/codeql-cli/creating-codeql-databases.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 8810e3deb9d..9cdd02f78fc 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -171,8 +171,9 @@ build steps, you may need to explicitly define each step in the command line.
The Go autobuilder attempts to automatically detect Go code in a repository,
and only runs build scripts in an attempt to fetch dependencies. To force
- CodeQL to use your build script, set the environment variable
- `CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or use the ``--command`` option.
+ CodeQL to limit extraction to the files compiled by your build script, set the environment variable
+ `CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or use the ``--command`` option to specify a
+ build command.
Specifying build commands
~~~~~~~~~~~~~~~~~~~~~~~~~
From 0e99d5e379041cdffcaab2da4e57218648d1fd96 Mon Sep 17 00:00:00 2001
From: Ethan P <56270045+ethanpalm@users.noreply.github.com>
Date: Fri, 14 May 2021 14:05:55 -0400
Subject: [PATCH 146/168] Add examples of both tracing mechanisms
---
docs/codeql/codeql-cli/creating-codeql-databases.rst | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 9cdd02f78fc..8658da9a1d4 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -202,9 +202,12 @@ commands that you can specify for compiled languages.
codeql database create csharp-database --language=csharp --command='dotnet build /p:UseSharedCompilation=false /t:rebuild'
+- Go project built using the ``COEQL_EXTRACTOR_GO_BUILD_TRACING=on`` environment variable::
+ CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
+
- Go project built using a custom build script::
- CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go --command='./scripts/build.sh'
+ codeql database create go-database --language=go --command='./scripts/build.sh'
- Java project built using Gradle::
From 58c746e42b174c1ee4465569e832c7a7cb735d03 Mon Sep 17 00:00:00 2001
From: Ethan P <56270045+ethanpalm@users.noreply.github.com>
Date: Fri, 14 May 2021 14:09:07 -0400
Subject: [PATCH 147/168] fix formatting
---
docs/codeql/codeql-cli/creating-codeql-databases.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 8658da9a1d4..1552a077e24 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -203,6 +203,7 @@ commands that you can specify for compiled languages.
codeql database create csharp-database --language=csharp --command='dotnet build /p:UseSharedCompilation=false /t:rebuild'
- Go project built using the ``COEQL_EXTRACTOR_GO_BUILD_TRACING=on`` environment variable::
+
CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
- Go project built using a custom build script::
From 31091c66c19fdb401967decc596621fa68db8d0a Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 17 May 2021 08:06:06 +0200
Subject: [PATCH 148/168] C++: Add a test containing a guarded long.
---
.../TaintedAllocationSize.expected | 332 +++++++++---------
.../semmle/TaintedAllocationSize/test.cpp | 10 +
2 files changed, 181 insertions(+), 161 deletions(-)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
index 234efe2c35b..752e9165c07 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected
@@ -1,164 +1,174 @@
edges
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... |
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... |
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted |
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted |
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted |
-| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted |
-| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size |
-| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
-| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... |
-| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... |
-| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... |
-| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... |
-| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... |
-| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... |
-| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... |
-| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... |
-| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... |
-| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size |
-| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size |
-| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store |
-| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:42 | Store |
-| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s |
-| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s |
-| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s |
-| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s |
-| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... |
-| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size |
-| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size |
-| test.cpp:227:24:227:29 | call to getenv | test.cpp:235:2:235:9 | local_size |
-| test.cpp:227:24:227:29 | call to getenv | test.cpp:237:2:237:8 | local_size |
-| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... |
-| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size |
-| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size |
-| test.cpp:227:24:227:37 | (const char *)... | test.cpp:235:2:235:9 | local_size |
-| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:2:237:8 | local_size |
-| test.cpp:235:2:235:9 | local_size | test.cpp:214:23:214:23 | s |
-| test.cpp:237:2:237:8 | local_size | test.cpp:220:21:220:21 | s |
-| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] |
-| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] |
-| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi [array content] |
-| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi [array content] |
-| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
-| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
-| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
-| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
-| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... |
-| test.cpp:279:17:279:20 | Chi | test.cpp:281:11:281:28 | ... * ... |
-| test.cpp:279:17:279:20 | get_size output argument [array content] | test.cpp:279:17:279:20 | Chi |
-| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
-| test.cpp:295:18:295:21 | Chi | test.cpp:298:10:298:27 | ... * ... |
-| test.cpp:295:18:295:21 | get_size output argument [array content] | test.cpp:295:18:295:21 | Chi |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | (size_t)... |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | (size_t)... |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
+| test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted |
+| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | (size_t)... |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | (size_t)... |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size |
+| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
+| test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... |
+| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
+| test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... |
+| test.cpp:124:18:124:31 | (const char *)... | test.cpp:128:24:128:41 | ... * ... |
+| test.cpp:124:18:124:31 | (const char *)... | test.cpp:128:24:128:41 | ... * ... |
+| test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
+| test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... |
+| test.cpp:133:19:133:32 | (const char *)... | test.cpp:135:10:135:27 | ... * ... |
+| test.cpp:133:19:133:32 | (const char *)... | test.cpp:135:10:135:27 | ... * ... |
+| test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
+| test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... |
+| test.cpp:148:20:148:33 | (const char *)... | test.cpp:152:11:152:28 | ... * ... |
+| test.cpp:148:20:148:33 | (const char *)... | test.cpp:152:11:152:28 | ... * ... |
+| test.cpp:211:9:211:42 | Store | test.cpp:241:9:241:24 | call to get_tainted_size |
+| test.cpp:211:9:211:42 | Store | test.cpp:241:9:241:24 | call to get_tainted_size |
+| test.cpp:211:14:211:19 | call to getenv | test.cpp:211:9:211:42 | Store |
+| test.cpp:211:14:211:27 | (const char *)... | test.cpp:211:9:211:42 | Store |
+| test.cpp:224:23:224:23 | s | test.cpp:225:21:225:21 | s |
+| test.cpp:224:23:224:23 | s | test.cpp:225:21:225:21 | s |
+| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
+| test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s |
+| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | (size_t)... |
+| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
+| test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size |
+| test.cpp:237:24:237:29 | call to getenv | test.cpp:245:2:245:9 | local_size |
+| test.cpp:237:24:237:29 | call to getenv | test.cpp:247:2:247:8 | local_size |
+| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | (size_t)... |
+| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
+| test.cpp:237:24:237:37 | (const char *)... | test.cpp:239:9:239:18 | local_size |
+| test.cpp:237:24:237:37 | (const char *)... | test.cpp:245:2:245:9 | local_size |
+| test.cpp:237:24:237:37 | (const char *)... | test.cpp:247:2:247:8 | local_size |
+| test.cpp:245:2:245:9 | local_size | test.cpp:224:23:224:23 | s |
+| test.cpp:247:2:247:8 | local_size | test.cpp:230:21:230:21 | s |
+| test.cpp:251:2:251:32 | Chi [array content] | test.cpp:289:17:289:20 | get_size output argument [array content] |
+| test.cpp:251:2:251:32 | Chi [array content] | test.cpp:305:18:305:21 | get_size output argument [array content] |
+| test.cpp:251:18:251:23 | call to getenv | test.cpp:251:2:251:32 | Chi [array content] |
+| test.cpp:251:18:251:31 | (const char *)... | test.cpp:251:2:251:32 | Chi [array content] |
+| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
+| test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... |
+| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
+| test.cpp:259:20:259:33 | (const char *)... | test.cpp:263:11:263:29 | ... * ... |
+| test.cpp:289:17:289:20 | Chi | test.cpp:291:11:291:28 | ... * ... |
+| test.cpp:289:17:289:20 | Chi | test.cpp:291:11:291:28 | ... * ... |
+| test.cpp:289:17:289:20 | get_size output argument [array content] | test.cpp:289:17:289:20 | Chi |
+| test.cpp:305:18:305:21 | Chi | test.cpp:308:10:308:27 | ... * ... |
+| test.cpp:305:18:305:21 | Chi | test.cpp:308:10:308:27 | ... * ... |
+| test.cpp:305:18:305:21 | get_size output argument [array content] | test.cpp:305:18:305:21 | Chi |
nodes
-| test.cpp:39:21:39:24 | argv | semmle.label | argv |
-| test.cpp:39:21:39:24 | argv | semmle.label | argv |
-| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:42:38:42:44 | tainted | semmle.label | tainted |
-| test.cpp:42:38:42:44 | tainted | semmle.label | tainted |
-| test.cpp:42:38:42:44 | tainted | semmle.label | tainted |
-| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... |
-| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... |
-| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... |
-| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... |
-| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... |
-| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... |
-| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:48:32:48:35 | size | semmle.label | size |
-| test.cpp:48:32:48:35 | size | semmle.label | size |
-| test.cpp:48:32:48:35 | size | semmle.label | size |
-| test.cpp:49:26:49:29 | size | semmle.label | size |
-| test.cpp:49:26:49:29 | size | semmle.label | size |
-| test.cpp:49:26:49:29 | size | semmle.label | size |
-| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
-| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
-| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... |
-| test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv |
-| test.cpp:123:18:123:31 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... |
-| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... |
-| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... |
-| test.cpp:132:19:132:24 | call to getenv | semmle.label | call to getenv |
-| test.cpp:132:19:132:32 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:201:9:201:42 | Store | semmle.label | Store |
-| test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv |
-| test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:214:23:214:23 | s | semmle.label | s |
-| test.cpp:215:21:215:21 | s | semmle.label | s |
-| test.cpp:215:21:215:21 | s | semmle.label | s |
-| test.cpp:215:21:215:21 | s | semmle.label | s |
-| test.cpp:220:21:220:21 | s | semmle.label | s |
-| test.cpp:221:21:221:21 | s | semmle.label | s |
-| test.cpp:221:21:221:21 | s | semmle.label | s |
-| test.cpp:221:21:221:21 | s | semmle.label | s |
-| test.cpp:227:24:227:29 | call to getenv | semmle.label | call to getenv |
-| test.cpp:227:24:227:37 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... |
-| test.cpp:229:9:229:18 | local_size | semmle.label | local_size |
-| test.cpp:229:9:229:18 | local_size | semmle.label | local_size |
-| test.cpp:229:9:229:18 | local_size | semmle.label | local_size |
-| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
-| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
-| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
-| test.cpp:235:2:235:9 | local_size | semmle.label | local_size |
-| test.cpp:237:2:237:8 | local_size | semmle.label | local_size |
-| test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] |
-| test.cpp:241:2:241:32 | ChiPartial | semmle.label | ChiPartial |
-| test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv |
-| test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv |
-| test.cpp:249:20:249:33 | (const char *)... | semmle.label | (const char *)... |
-| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
-| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
-| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
-| test.cpp:279:17:279:20 | Chi | semmle.label | Chi |
-| test.cpp:279:17:279:20 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
-| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
-| test.cpp:295:18:295:21 | Chi | semmle.label | Chi |
-| test.cpp:295:18:295:21 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
-| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
-| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:40:21:40:24 | argv | semmle.label | argv |
+| test.cpp:40:21:40:24 | argv | semmle.label | argv |
+| test.cpp:43:38:43:44 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:43:38:43:44 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
+| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
+| test.cpp:43:38:43:44 | tainted | semmle.label | tainted |
+| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
+| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
+| test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... |
+| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
+| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
+| test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... |
+| test.cpp:49:32:49:35 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:49:32:49:35 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:49:32:49:35 | size | semmle.label | size |
+| test.cpp:49:32:49:35 | size | semmle.label | size |
+| test.cpp:49:32:49:35 | size | semmle.label | size |
+| test.cpp:50:26:50:29 | size | semmle.label | size |
+| test.cpp:50:26:50:29 | size | semmle.label | size |
+| test.cpp:50:26:50:29 | size | semmle.label | size |
+| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
+| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
+| test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... |
+| test.cpp:124:18:124:23 | call to getenv | semmle.label | call to getenv |
+| test.cpp:124:18:124:31 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
+| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
+| test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... |
+| test.cpp:133:19:133:24 | call to getenv | semmle.label | call to getenv |
+| test.cpp:133:19:133:32 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:148:20:148:25 | call to getenv | semmle.label | call to getenv |
+| test.cpp:148:20:148:33 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:211:9:211:42 | Store | semmle.label | Store |
+| test.cpp:211:14:211:19 | call to getenv | semmle.label | call to getenv |
+| test.cpp:211:14:211:27 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:224:23:224:23 | s | semmle.label | s |
+| test.cpp:225:21:225:21 | s | semmle.label | s |
+| test.cpp:225:21:225:21 | s | semmle.label | s |
+| test.cpp:225:21:225:21 | s | semmle.label | s |
+| test.cpp:230:21:230:21 | s | semmle.label | s |
+| test.cpp:231:21:231:21 | s | semmle.label | s |
+| test.cpp:231:21:231:21 | s | semmle.label | s |
+| test.cpp:231:21:231:21 | s | semmle.label | s |
+| test.cpp:237:24:237:29 | call to getenv | semmle.label | call to getenv |
+| test.cpp:237:24:237:37 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:239:9:239:18 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:239:9:239:18 | (size_t)... | semmle.label | (size_t)... |
+| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
+| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
+| test.cpp:239:9:239:18 | local_size | semmle.label | local_size |
+| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
+| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
+| test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
+| test.cpp:245:2:245:9 | local_size | semmle.label | local_size |
+| test.cpp:247:2:247:8 | local_size | semmle.label | local_size |
+| test.cpp:251:2:251:32 | Chi [array content] | semmle.label | Chi [array content] |
+| test.cpp:251:2:251:32 | ChiPartial | semmle.label | ChiPartial |
+| test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv |
+| test.cpp:251:18:251:31 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:259:20:259:25 | call to getenv | semmle.label | call to getenv |
+| test.cpp:259:20:259:33 | (const char *)... | semmle.label | (const char *)... |
+| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
+| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
+| test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... |
+| test.cpp:289:17:289:20 | Chi | semmle.label | Chi |
+| test.cpp:289:17:289:20 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
+| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... |
+| test.cpp:305:18:305:21 | Chi | semmle.label | Chi |
+| test.cpp:305:18:305:21 | get_size output argument [array content] | semmle.label | get_size output argument [array content] |
+| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
+| test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... |
#select
-| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
-| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) |
-| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) |
-| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
-| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
-| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
-| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) |
-| test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (getenv) |
-| test.cpp:281:4:281:9 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:281:11:281:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
-| test.cpp:298:3:298:8 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:298:10:298:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
+| test.cpp:43:31:43:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:44:31:44:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:46:31:46:36 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:49:25:49:30 | call to malloc | test.cpp:40:21:40:24 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:50:17:50:30 | new[] | test.cpp:40:21:40:24 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:53:21:53:27 | call to realloc | test.cpp:40:21:40:24 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:40:21:40:24 | argv | user input (argv) |
+| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:124:18:124:23 | call to getenv | user input (getenv) |
+| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:133:19:133:24 | call to getenv | user input (getenv) |
+| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:148:20:148:25 | call to getenv | user input (getenv) |
+| test.cpp:225:14:225:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:225:21:225:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
+| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
+| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:237:24:237:29 | call to getenv | user input (getenv) |
+| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:211:14:211:19 | call to getenv | user input (getenv) |
+| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:259:20:259:25 | call to getenv | user input (getenv) |
+| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (getenv) |
+| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:251:18:251:23 | call to getenv | user input (getenv) |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
index 57eb5b91a07..b11a136ed24 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp
@@ -7,6 +7,7 @@ void *malloc(size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
int atoi(const char *nptr);
+long atol(const char *nptr);
struct MyStruct
{
char data[256];
@@ -143,6 +144,15 @@ void more_bounded_tests() {
}
}
+ {
+ long size = atol(getenv("USER"));
+
+ if (size > 0)
+ {
+ malloc(size * sizeof(int)); // BAD
+ }
+ }
+
{
int size = atoi(getenv("USER"));
From b142ecb1dbc73e269b912719ca41f9c3684e56e5 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 17 May 2021 10:33:06 +0200
Subject: [PATCH 149/168] C#: Address review comment
---
csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs | 6 ------
1 file changed, 6 deletions(-)
diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
index 955775d0f66..3d7a1168e30 100644
--- a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
+++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs
@@ -236,12 +236,6 @@ namespace Semmle.Autobuild.CSharp
///
/// Gets the `dotnet build` script.
- ///
- /// The CLR tracer only works on .NET Core >= 3 on Linux and macOS (see
- /// https://github.com/dotnet/coreclr/issues/19622), so in case we are
- /// running on an older .NET Core, we disable shared compilation (and
- /// hence the need for CLR tracing), by adding a
- /// `/p:UseSharedCompilation=false` argument.
///
private static BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary? environment, string projOrSln)
{
From 77c93dcf26fa083cc7fffc8e6b53a8bc59c169e1 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Mon, 17 May 2021 10:35:04 +0200
Subject: [PATCH 150/168] Make private
---
.../code/java/frameworks/jackson/JacksonSerializability.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
index 50266c377f8..6cda84512a0 100644
--- a/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
+++ b/java/ql/src/semmle/code/java/frameworks/jackson/JacksonSerializability.qll
@@ -156,7 +156,7 @@ class JacksonDeserializableField extends DeserializableField {
}
/** A call to a field that may be deserialized using the Jackson JSON framework. */
-class JacksonDeserializableFieldAccess extends FieldAccess {
+private class JacksonDeserializableFieldAccess extends FieldAccess {
JacksonDeserializableFieldAccess() { getField() instanceof JacksonDeserializableField }
}
@@ -164,7 +164,7 @@ class JacksonDeserializableFieldAccess extends FieldAccess {
* When an object is deserialized by the Jackson JSON framework using a tainted input source,
* the fields that the framework deserialized are themselves tainted input data.
*/
-class JacksonDeserializedTaintStep extends AdditionalTaintStep {
+private class JacksonDeserializedTaintStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
DataFlow::getFieldQualifier(node2.asExpr().(JacksonDeserializableFieldAccess)) = node1
}
From e652d8771c343c819d62d1901593185af2506d25 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Mon, 17 May 2021 20:34:16 +0000
Subject: [PATCH 151/168] Update method name and qldoc
---
.../Security/CWE/CWE-094/JythonInjection.ql | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
index 0f23edc69f4..06b077446e2 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
@@ -52,7 +52,7 @@ class LoadClassMethod extends Method {
* Holds if `ma` is a call to a class-loading method, and `sink` is the byte array
* representing the class to be loaded.
*/
-predicate loadClass(MethodAccess ma, Expr sink) {
+predicate loadsClass(MethodAccess ma, Expr sink) {
exists(Method m, int i | m = ma.getMethod() |
m instanceof LoadClassMethod and
m.getParameter(i).getType() instanceof Array and // makeClass(java.lang.String name, byte[] data, ...)
@@ -85,17 +85,21 @@ predicate compile(MethodAccess ma, Expr sink) {
class CodeInjectionSink extends DataFlow::ExprNode {
CodeInjectionSink() {
runCode(_, this.getExpr()) or
- loadClass(_, this.getExpr()) or
+ loadsClass(_, this.getExpr()) or
compile(_, this.getExpr())
}
MethodAccess getMethodAccess() {
runCode(result, this.getExpr()) or
- loadClass(result, this.getExpr()) or
+ loadsClass(result, this.getExpr()) or
compile(result, this.getExpr())
}
}
+/**
+ * A taint configuration for tracking flow from `RemoteFlowSource` to a Jython method call
+ * `CodeInjectionSink` that executes injected code.
+ */
class CodeInjectionConfiguration extends TaintTracking::Configuration {
CodeInjectionConfiguration() { this = "CodeInjectionConfiguration" }
From a0cd551bae9ae005c59657ef3463817e226cfe29 Mon Sep 17 00:00:00 2001
From: haby0
Date: Tue, 18 May 2021 11:05:10 +0800
Subject: [PATCH 152/168] Add filtering of String.format
---
.../Security/CWE/CWE-601/SpringUrlRedirect.ql | 10 +++
.../CWE/CWE-601/SpringUrlRedirect.qll | 61 +------------------
.../CWE-601/SpringUrlRedirect.expected | 8 +++
.../security/CWE-601/SpringUrlRedirect.java | 17 +++++-
4 files changed, 37 insertions(+), 59 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
index 138bce57ac9..5c8a8ea78d8 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
@@ -33,6 +33,16 @@ class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
ae.getRightOperand() = node.asExpr() and
not ae instanceof RedirectBuilderExpr
)
+ or
+ exists(MethodAccess ma, int index |
+ ma.getMethod().hasName("format") and
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getArgument(index) = node.asExpr() and
+ (
+ index != 0 and
+ not ma.getArgument(0).(CompileTimeConstantExpr).getStringValue().regexpMatch("^%s.*")
+ )
+ )
}
}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
index 866eaae1c34..84bb5d9adf8 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -51,14 +51,14 @@ class SpringUrlRedirectSink extends DataFlow::Node {
SpringUrlRedirectSink() {
exists(RedirectBuilderExpr rbe |
rbe.getRightOperand() = this.asExpr() and
- exists(RedirectBuilderFlowConfig rbfc | rbfc.hasFlow(exprNode(rbe), _))
+ any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
)
or
exists(MethodAccess ma, RedirectAppendCall rac |
DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and
ma.getMethod().hasName("append") and
ma.getArgument(0) = this.asExpr() and
- exists(RedirectBuilderFlowConfig rbfc | rbfc.hasFlow(exprNode(ma.getQualifier()), _))
+ any(SpringRequestMappingMethod sqmm).polyCalls*(this.getEnclosingCallable())
)
or
exists(MethodAccess ma |
@@ -66,8 +66,7 @@ class SpringUrlRedirectSink extends DataFlow::Node {
ma.getMethod()
.getDeclaringType()
.hasQualifiedName("org.springframework.web.servlet.view", "AbstractUrlBasedView") and
- ma.getArgument(0) = this.asExpr() and
- exists(RedirectViewFlowConfig rvfc | rvfc.hasFlowToExpr(ma.getQualifier()))
+ ma.getArgument(0) = this.asExpr()
)
or
exists(ClassInstanceExpr cie |
@@ -84,57 +83,3 @@ class SpringUrlRedirectSink extends DataFlow::Node {
)
}
}
-
-/** A data flow configuration tracing flow from redirect builder expression to spring controller method return expression. */
-private class RedirectBuilderFlowConfig extends DataFlow2::Configuration {
- RedirectBuilderFlowConfig() { this = "RedirectBuilderFlowConfig" }
-
- override predicate isSource(DataFlow::Node src) {
- exists(RedirectBuilderExpr rbe | rbe = src.asExpr())
- or
- exists(MethodAccess ma, RedirectAppendCall rac |
- DataFlow2::localExprFlow(rac.getQualifier(), ma.getQualifier()) and
- ma.getMethod().hasName("append") and
- ma.getQualifier() = src.asExpr()
- )
- }
-
- override predicate isSink(DataFlow::Node sink) {
- exists(ReturnStmt rs, SpringRequestMappingMethod sqmm |
- rs.getResult() = sink.asExpr() and
- sqmm.getBody().getAStmt() = rs
- )
- }
-
- override predicate isAdditionalFlowStep(Node prod, Node succ) {
- exists(MethodAccess ma |
- ma.getMethod().hasName("toString") and
- ma.getMethod().getDeclaringType() instanceof StringBuildingType and
- ma.getQualifier() = prod.asExpr() and
- ma = succ.asExpr()
- )
- }
-}
-
-/** A data flow configuration tracing flow from RedirectView object to calling setUrl method. */
-private class RedirectViewFlowConfig extends DataFlow2::Configuration {
- RedirectViewFlowConfig() { this = "RedirectViewFlowConfig" }
-
- override predicate isSource(DataFlow::Node src) {
- exists(ClassInstanceExpr cie |
- cie.getConstructedType()
- .hasQualifiedName("org.springframework.web.servlet.view", "RedirectView") and
- cie = src.asExpr()
- )
- }
-
- override predicate isSink(DataFlow::Node sink) {
- exists(MethodAccess ma |
- ma.getMethod().hasName("setUrl") and
- ma.getMethod()
- .getDeclaringType()
- .hasQualifiedName("org.springframework.web.servlet.view", "AbstractUrlBasedView") and
- ma.getQualifier() = sink.asExpr()
- )
- }
-}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
index 26b8acd7770..bcf5e892e1b 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.expected
@@ -5,6 +5,8 @@ edges
| SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl |
| SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl |
| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl |
+| SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | SpringUrlRedirect.java:54:30:54:66 | format(...) |
+| SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | SpringUrlRedirect.java:59:30:59:76 | format(...) |
nodes
| SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | semmle.label | redirectUrl |
@@ -18,6 +20,10 @@ nodes
| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | semmle.label | redirectUrl |
| SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | semmle.label | redirectUrl : String |
| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | semmle.label | redirectUrl |
+| SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:54:30:54:66 | format(...) | semmle.label | format(...) |
+| SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | semmle.label | redirectUrl : String |
+| SpringUrlRedirect.java:59:30:59:76 | format(...) | semmle.label | format(...) |
#select
| SpringUrlRedirect.java:15:19:15:29 | redirectUrl | SpringUrlRedirect.java:13:30:13:47 | redirectUrl : String | SpringUrlRedirect.java:15:19:15:29 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:13:30:13:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:21:36:21:46 | redirectUrl | SpringUrlRedirect.java:20:24:20:41 | redirectUrl : String | SpringUrlRedirect.java:21:36:21:46 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:20:24:20:41 | redirectUrl | user-provided value |
@@ -25,3 +31,5 @@ nodes
| SpringUrlRedirect.java:33:47:33:57 | redirectUrl | SpringUrlRedirect.java:32:30:32:47 | redirectUrl : String | SpringUrlRedirect.java:33:47:33:57 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:32:30:32:47 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:40:29:40:39 | redirectUrl | SpringUrlRedirect.java:37:24:37:41 | redirectUrl : String | SpringUrlRedirect.java:40:29:40:39 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:37:24:37:41 | redirectUrl | user-provided value |
| SpringUrlRedirect.java:48:30:48:40 | redirectUrl | SpringUrlRedirect.java:45:24:45:41 | redirectUrl : String | SpringUrlRedirect.java:48:30:48:40 | redirectUrl | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:45:24:45:41 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:54:30:54:66 | format(...) | SpringUrlRedirect.java:53:24:53:41 | redirectUrl : String | SpringUrlRedirect.java:54:30:54:66 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:53:24:53:41 | redirectUrl | user-provided value |
+| SpringUrlRedirect.java:59:30:59:76 | format(...) | SpringUrlRedirect.java:58:24:58:41 | redirectUrl : String | SpringUrlRedirect.java:59:30:59:76 | format(...) | Potentially untrusted URL redirection due to $@. | SpringUrlRedirect.java:58:24:58:41 | redirectUrl | user-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
index 5124d8cd8c6..f3958cba102 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-601/SpringUrlRedirect.java
@@ -50,6 +50,16 @@ public class SpringUrlRedirect {
}
@GetMapping("url7")
+ public String bad7(String redirectUrl) {
+ return "redirect:" + String.format("%s/?aaa", redirectUrl);
+ }
+
+ @GetMapping("url8")
+ public String bad8(String redirectUrl, String token) {
+ return "redirect:" + String.format(redirectUrl + "?token=%s", token);
+ }
+
+ @GetMapping("url9")
public RedirectView good1(String redirectUrl) {
RedirectView rv = new RedirectView();
if (redirectUrl.startsWith(VALID_REDIRECT)){
@@ -60,9 +70,14 @@ public class SpringUrlRedirect {
return rv;
}
- @GetMapping("url8")
+ @GetMapping("url10")
public ModelAndView good2(String token) {
String url = "/edit?token=" + token;
return new ModelAndView("redirect:" + url);
}
+
+ @GetMapping("url11")
+ public String good3(String status) {
+ return "redirect:" + String.format("/stories/search/criteria?status=%s", status);
+ }
}
From 1435ac715ac6d7f3f5255c7069e305620cc6afd2 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 May 2021 12:46:34 +0200
Subject: [PATCH 153/168] add support for the clone library
---
javascript/change-notes/2021-05-18-clone.md | 4 ++++
javascript/ql/src/javascript.qll | 1 +
.../src/semmle/javascript/frameworks/Clone.qll | 15 +++++++++++++++
.../CWE-079/ReflectedXss/ReflectedXss.expected | 17 +++++++++++++++++
.../ReflectedXssWithCustomSanitizer.expected | 2 ++
.../Security/CWE-079/ReflectedXss/tst2.js | 14 ++++++++++++++
6 files changed, 53 insertions(+)
create mode 100644 javascript/change-notes/2021-05-18-clone.md
create mode 100644 javascript/ql/src/semmle/javascript/frameworks/Clone.qll
diff --git a/javascript/change-notes/2021-05-18-clone.md b/javascript/change-notes/2021-05-18-clone.md
new file mode 100644
index 00000000000..42d52d72a3d
--- /dev/null
+++ b/javascript/change-notes/2021-05-18-clone.md
@@ -0,0 +1,4 @@
+lgtm,codescanning
+* The dataflow libraries now model dataflow in the `clone` library.
+ Affected packages are
+ [clone](https://npmjs.com/package/clone)
diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll
index 95db948bbd4..a46313f47f0 100644
--- a/javascript/ql/src/javascript.qll
+++ b/javascript/ql/src/javascript.qll
@@ -78,6 +78,7 @@ import semmle.javascript.frameworks.ComposedFunctions
import semmle.javascript.frameworks.Classnames
import semmle.javascript.frameworks.ClassValidator
import semmle.javascript.frameworks.ClientRequests
+import semmle.javascript.frameworks.Clone
import semmle.javascript.frameworks.ClosureLibrary
import semmle.javascript.frameworks.CookieLibraries
import semmle.javascript.frameworks.Credentials
diff --git a/javascript/ql/src/semmle/javascript/frameworks/Clone.qll b/javascript/ql/src/semmle/javascript/frameworks/Clone.qll
new file mode 100644
index 00000000000..5aabee438c5
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/frameworks/Clone.qll
@@ -0,0 +1,15 @@
+/**
+ * Provides a dataflow-step for the `clone` package.
+ */
+
+import javascript
+private import semmle.javascript.dataflow.internal.PreCallGraphStep
+
+private class CloneStep extends PreCallGraphStep {
+ override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
+ exists(DataFlow::CallNode call | call = DataFlow::moduleImport("clone").getACall() |
+ pred = call.getArgument(0) and
+ succ = call
+ )
+ }
+}
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected
index f8ceeb45b62..e8d093325ad 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected
@@ -174,6 +174,14 @@ nodes
| tst2.js:18:12:18:12 | p |
| tst2.js:21:14:21:14 | p |
| tst2.js:21:14:21:14 | p |
+| tst2.js:30:7:30:24 | p |
+| tst2.js:30:9:30:9 | p |
+| tst2.js:30:9:30:9 | p |
+| tst2.js:33:11:33:11 | p |
+| tst2.js:36:12:36:12 | p |
+| tst2.js:36:12:36:12 | p |
+| tst2.js:37:12:37:18 | other.p |
+| tst2.js:37:12:37:18 | other.p |
edges
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
@@ -318,6 +326,13 @@ edges
| tst2.js:14:7:14:24 | p | tst2.js:21:14:21:14 | p |
| tst2.js:14:9:14:9 | p | tst2.js:14:7:14:24 | p |
| tst2.js:14:9:14:9 | p | tst2.js:14:7:14:24 | p |
+| tst2.js:30:7:30:24 | p | tst2.js:33:11:33:11 | p |
+| tst2.js:30:7:30:24 | p | tst2.js:36:12:36:12 | p |
+| tst2.js:30:7:30:24 | p | tst2.js:36:12:36:12 | p |
+| tst2.js:30:9:30:9 | p | tst2.js:30:7:30:24 | p |
+| tst2.js:30:9:30:9 | p | tst2.js:30:7:30:24 | p |
+| tst2.js:33:11:33:11 | p | tst2.js:37:12:37:18 | other.p |
+| tst2.js:33:11:33:11 | p | tst2.js:37:12:37:18 | other.p |
#select
| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
| ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | ReflectedXss.js:17:31:17:39 | params.id | ReflectedXss.js:17:12:17:39 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:17:31:17:39 | params.id | user-provided value |
@@ -359,3 +374,5 @@ edges
| tst2.js:8:12:8:12 | r | tst2.js:6:12:6:15 | q: r | tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
| tst2.js:18:12:18:12 | p | tst2.js:14:9:14:9 | p | tst2.js:18:12:18:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:14:9:14:9 | p | user-provided value |
| tst2.js:21:14:21:14 | p | tst2.js:14:9:14:9 | p | tst2.js:21:14:21:14 | p | Cross-site scripting vulnerability due to $@. | tst2.js:14:9:14:9 | p | user-provided value |
+| tst2.js:36:12:36:12 | p | tst2.js:30:9:30:9 | p | tst2.js:36:12:36:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
+| tst2.js:37:12:37:18 | other.p | tst2.js:30:9:30:9 | p | tst2.js:37:12:37:18 | other.p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected
index 719a82171a8..8ddc55dde36 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected
@@ -37,3 +37,5 @@
| tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
| tst2.js:18:12:18:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:14:9:14:9 | p | user-provided value |
| tst2.js:21:14:21:14 | p | Cross-site scripting vulnerability due to $@. | tst2.js:14:9:14:9 | p | user-provided value |
+| tst2.js:36:12:36:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
+| tst2.js:37:12:37:18 | other.p | Cross-site scripting vulnerability due to $@. | tst2.js:30:9:30:9 | p | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/tst2.js b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/tst2.js
index 521b6b20a7c..034b0791217 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/tst2.js
+++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/tst2.js
@@ -22,3 +22,17 @@ app.get('/bar', function(req, res) {
else
res.send(p); // OK
});
+
+
+const clone = require('clone');
+
+app.get('/baz', function(req, res) {
+ let { p } = req.params;
+
+ var obj = {};
+ obj.p = p;
+ var other = clone(obj);
+
+ res.send(p); // NOT OK
+ res.send(other.p); // NOT OK
+});
\ No newline at end of file
From caf5f4d605bbdcb67fa65de5b65f9288a39d8ef4 Mon Sep 17 00:00:00 2001
From: haby0
Date: Tue, 18 May 2021 19:10:03 +0800
Subject: [PATCH 154/168] modified comment
---
.../src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql | 2 ++
.../src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
index 5c8a8ea78d8..210067fde2a 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
@@ -29,6 +29,8 @@ class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) {
// Exclude the case where the left side of the concatenated string is not `redirect:`.
// E.g: `String url = "/path?token=" + request.getParameter("token");`
+ // Note this is quite a broad sanitizer (it will also sanitize the right-hand side of `url = "http://" + request.getParameter("token")`);
+ // Consider making this stricter in future.
exists(AddExpr ae |
ae.getRightOperand() = node.asExpr() and
not ae instanceof RedirectBuilderExpr
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
index 84bb5d9adf8..6ae87a37bcc 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -5,7 +5,7 @@ import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.spring.SpringController
-class StartsWithSanitizer extends DataFlow::BarrierGuard {
+private class StartsWithSanitizer extends DataFlow::BarrierGuard {
StartsWithSanitizer() {
this.(MethodAccess).getMethod().hasName("startsWith") and
this.(MethodAccess).getMethod().getDeclaringType() instanceof TypeString and
From 06514a2bb6c3577269c312910e1d3c15764a6347 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 May 2021 13:16:41 +0200
Subject: [PATCH 155/168] move clone model to Extend.qll
---
javascript/ql/src/javascript.qll | 1 -
javascript/ql/src/semmle/javascript/Extend.qll | 14 ++++++++++++++
.../ql/src/semmle/javascript/frameworks/Clone.qll | 15 ---------------
3 files changed, 14 insertions(+), 16 deletions(-)
delete mode 100644 javascript/ql/src/semmle/javascript/frameworks/Clone.qll
diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll
index a46313f47f0..95db948bbd4 100644
--- a/javascript/ql/src/javascript.qll
+++ b/javascript/ql/src/javascript.qll
@@ -78,7 +78,6 @@ import semmle.javascript.frameworks.ComposedFunctions
import semmle.javascript.frameworks.Classnames
import semmle.javascript.frameworks.ClassValidator
import semmle.javascript.frameworks.ClientRequests
-import semmle.javascript.frameworks.Clone
import semmle.javascript.frameworks.ClosureLibrary
import semmle.javascript.frameworks.CookieLibraries
import semmle.javascript.frameworks.Credentials
diff --git a/javascript/ql/src/semmle/javascript/Extend.qll b/javascript/ql/src/semmle/javascript/Extend.qll
index 9b7255983b9..d50054fc4ee 100644
--- a/javascript/ql/src/semmle/javascript/Extend.qll
+++ b/javascript/ql/src/semmle/javascript/Extend.qll
@@ -174,3 +174,17 @@ private class ExtendCallTaintStep extends TaintTracking::SharedTaintStep {
)
}
}
+
+private import semmle.javascript.dataflow.internal.PreCallGraphStep
+
+/**
+ * A step for the `clone` package.
+ */
+private class CloneStep extends PreCallGraphStep {
+ override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
+ exists(DataFlow::CallNode call | call = DataFlow::moduleImport("clone").getACall() |
+ pred = call.getArgument(0) and
+ succ = call
+ )
+ }
+}
diff --git a/javascript/ql/src/semmle/javascript/frameworks/Clone.qll b/javascript/ql/src/semmle/javascript/frameworks/Clone.qll
deleted file mode 100644
index 5aabee438c5..00000000000
--- a/javascript/ql/src/semmle/javascript/frameworks/Clone.qll
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Provides a dataflow-step for the `clone` package.
- */
-
-import javascript
-private import semmle.javascript.dataflow.internal.PreCallGraphStep
-
-private class CloneStep extends PreCallGraphStep {
- override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
- exists(DataFlow::CallNode call | call = DataFlow::moduleImport("clone").getACall() |
- pred = call.getArgument(0) and
- succ = call
- )
- }
-}
From e46de44473791493bd73068dabced3be868da819 Mon Sep 17 00:00:00 2001
From: haby0
Date: Tue, 18 May 2021 19:56:32 +0800
Subject: [PATCH 156/168] Solve errors caused by private ownership
---
.../Security/CWE/CWE-601/SpringUrlRedirect.ql | 12 ++++++++++++
.../Security/CWE/CWE-601/SpringUrlRedirect.qll | 12 ------------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
index 210067fde2a..b02bd3e4c30 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.ql
@@ -15,6 +15,18 @@ import SpringUrlRedirect
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
+private class StartsWithSanitizer extends DataFlow::BarrierGuard {
+ StartsWithSanitizer() {
+ this.(MethodAccess).getMethod().hasName("startsWith") and
+ this.(MethodAccess).getMethod().getDeclaringType() instanceof TypeString and
+ this.(MethodAccess).getMethod().getNumberOfParameters() = 1
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and branch = true
+ }
+}
+
class SpringUrlRedirectFlowConfig extends TaintTracking::Configuration {
SpringUrlRedirectFlowConfig() { this = "SpringUrlRedirectFlowConfig" }
diff --git a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
index 6ae87a37bcc..4a86640d4d4 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-601/SpringUrlRedirect.qll
@@ -5,18 +5,6 @@ import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.spring.SpringController
-private class StartsWithSanitizer extends DataFlow::BarrierGuard {
- StartsWithSanitizer() {
- this.(MethodAccess).getMethod().hasName("startsWith") and
- this.(MethodAccess).getMethod().getDeclaringType() instanceof TypeString and
- this.(MethodAccess).getMethod().getNumberOfParameters() = 1
- }
-
- override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and branch = true
- }
-}
-
/**
* A concatenate expression using the string `redirect:` or `ajaxredirect:` or `forward:` on the left.
*
From 2a0721b2aeae25d99e1c5805311b8b6e46a735af Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 18 May 2021 12:18:14 +0000
Subject: [PATCH 157/168] Optimize the sink and update method name
---
.../Security/CWE/CWE-094/JythonInjection.ql | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
index 06b077446e2..c44eee23602 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/JythonInjection.ql
@@ -33,7 +33,7 @@ class BytecodeLoader extends RefType {
}
/** Holds if a Jython expression if evaluated, compiled or executed. */
-predicate runCode(MethodAccess ma, Expr sink) {
+predicate runsCode(MethodAccess ma, Expr sink) {
exists(Method m | m = ma.getMethod() |
m instanceof InterpretExprMethod and
sink = ma.getArgument(0)
@@ -83,17 +83,15 @@ predicate compile(MethodAccess ma, Expr sink) {
/** An expression loaded by Jython. */
class CodeInjectionSink extends DataFlow::ExprNode {
+ MethodAccess methodAccess;
+
CodeInjectionSink() {
- runCode(_, this.getExpr()) or
- loadsClass(_, this.getExpr()) or
- compile(_, this.getExpr())
+ runsCode(methodAccess, this.getExpr()) or
+ loadsClass(methodAccess, this.getExpr()) or
+ compile(methodAccess, this.getExpr())
}
- MethodAccess getMethodAccess() {
- runCode(result, this.getExpr()) or
- loadsClass(result, this.getExpr()) or
- compile(result, this.getExpr())
- }
+ MethodAccess getMethodAccess() { result = methodAccess }
}
/**
From 610e041e28a3c1d417e1e1c56fbccc7a2cb60896 Mon Sep 17 00:00:00 2001
From: Ethan Palm <56270045+ethanpalm@users.noreply.github.com>
Date: Tue, 18 May 2021 11:42:08 -0400
Subject: [PATCH 158/168] Add reviewer feedback
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
---
docs/codeql/codeql-cli/creating-codeql-databases.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst
index 1552a077e24..637df58555b 100644
--- a/docs/codeql/codeql-cli/creating-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst
@@ -169,7 +169,7 @@ build steps, you may need to explicitly define each step in the command line.
are dependencies, the appropriate dependency manager (such as `dep
`__).
- The Go autobuilder attempts to automatically detect Go code in a repository,
+ The Go autobuilder attempts to automatically detect code written in Go in a repository,
and only runs build scripts in an attempt to fetch dependencies. To force
CodeQL to limit extraction to the files compiled by your build script, set the environment variable
`CODEQL_EXTRACTOR_GO_BUILD_TRACING=on` or use the ``--command`` option to specify a
From b0b5338359ce7da9525f705d77784545f6090c8e Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Thu, 29 Apr 2021 02:59:41 +0000
Subject: [PATCH 159/168] Rhino code injection
---
.../Security/CWE/CWE-094/RhinoInjection.java | 39 ++
.../Security/CWE/CWE-094/RhinoInjection.qhelp | 51 ++
.../Security/CWE/CWE-094/RhinoInjection.ql | 17 +
.../Security/CWE/CWE-094/RhinoInjection.qll | 56 ++
.../security/CWE-094/RhinoInjection.expected | 7 +
.../security/CWE-094/RhinoInjection.qlref | 1 +
.../security/CWE-094/RhinoServlet.java | 78 +++
.../query-tests/security/CWE-094/options | 2 +-
.../org/mozilla/javascript/ClassShutter.java | 56 ++
.../org/mozilla/javascript/Context.java | 623 ++++++++++++++++++
.../mozilla/javascript/ContextFactory.java | 314 +++++++++
.../mozilla/javascript/RhinoException.java | 15 +
.../org/mozilla/javascript/Scriptable.java | 304 +++++++++
.../mozilla/javascript/ScriptableObject.java | 27 +
14 files changed, 1589 insertions(+), 1 deletion(-)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qhelp
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.expected
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.qlref
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ClassShutter.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Context.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ContextFactory.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/RhinoException.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Scriptable.java
create mode 100644 java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ScriptableObject.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
new file mode 100644
index 00000000000..4a87d5bc354
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
@@ -0,0 +1,39 @@
+public class RhinoInjection extends HttpServlet {
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ Context ctx = Context.enter();
+ try {
+ {
+ // BAD: allow arbitrary Java and JavaScript code to be executed
+ Scriptable scope = ctx.initStandardObjects();
+ }
+
+ {
+ // GOOD: enable the safe mode
+ Scriptable scope = ctx.initSafeStandardObjects();
+ }
+
+ {
+ // GOOD: enforce a constraint on allowed classes
+ Scriptable scope = ctx.initStandardObjects();
+ ctx.setClassShutter(new ClassShutter() {
+ public boolean visibleToScripts(String className) {
+ if(className.startsWith("com.example.")) {
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ Object result = ctx.evaluateString(scope, code, "", 1, null);
+ response.getWriter().print(Context.toString(result));
+ } catch(RhinoException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ Context.exit();
+ }
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qhelp
new file mode 100644
index 00000000000..73c252ed54c
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qhelp
@@ -0,0 +1,51 @@
+
+
+
+
+
+Rhino is a JavaScript engine written fully in Java and managed by the Mozilla Foundation.
+It serves as an embedded scripting engine inside Java applications which allows
+Java-to-JavaScript interoperability and provides a seamless integration between the two
+languages. If an expression is built using attacker-controlled data, and then evaluated in
+a powerful context, it may allow the attacker to run arbitrary code.
+
+
+Typically an expression is evaluated in the powerful context initialized with
+initStandardObjects that allows an expression of arbitrary Java code to
+execute in the JVM.
+
+
+
+
+
+In general, including user input in a Rhino expression should be avoided.
+If user input must be included in the expression, it should be then evaluated in a safe
+context that doesn't allow arbitrary code invocation.
+
+
+
+
+
+The following example shows two ways of using Rhino expression. In the 'BAD' case,
+an unsafe context is initialized with initStandardObjects. In the 'GOOD' case,
+a safe context is initialized with initSafeStandardObjects or
+setClassShutter.
+
+
+
\ No newline at end of file
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql
new file mode 100644
index 00000000000..cac41244aa2
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql
@@ -0,0 +1,17 @@
+/**
+ * @name Injection in Mozilla Rhino JavaScript Engine
+ * @description Evaluation of a user-controlled JavaScript or Java expression in Rhino
+ * JavaScript Engine may lead to remote code execution.
+ * @kind path-problem
+ * @id java/rhino-injection
+ * @tags security
+ * external/cwe/cwe-094
+ */
+
+import java
+import RhinoInjection
+import DataFlow::PathGraph
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, RhinoInjectionConfig conf
+where conf.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "Rhino injection from $@.", source.getNode(), " user input"
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll
new file mode 100644
index 00000000000..a560e340e85
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll
@@ -0,0 +1,56 @@
+import java
+import semmle.code.java.dataflow.FlowSources
+import semmle.code.java.dataflow.TaintTracking
+
+/** The class `org.mozilla.javascript.Context`. */
+class Context extends RefType {
+ Context() { this.hasQualifiedName("org.mozilla.javascript", "Context") }
+}
+
+/**
+ * A method that evaluates a Rhino expression.
+ */
+class EvaluateExpressionMethod extends Method {
+ EvaluateExpressionMethod() {
+ this.getDeclaringType().getAnAncestor*() instanceof Context and
+ (
+ hasName("evaluateString") or
+ hasName("evaluateReader")
+ )
+ }
+}
+
+/**
+ * A taint-tracking configuration for unsafe user input that is used to evaluate
+ * a Rhino expression.
+ */
+class RhinoInjectionConfig extends TaintTracking::Configuration {
+ RhinoInjectionConfig() { this = "RhinoInjectionConfig" }
+
+ override predicate isSource(DataFlow::Node source) {
+ source instanceof RemoteFlowSource
+ or
+ source instanceof LocalUserInput
+ }
+
+ override predicate isSink(DataFlow::Node sink) { sink instanceof EvaluateExpressionSink }
+}
+
+/**
+ * A sink for Rhino code injection vulnerabilities.
+ */
+class EvaluateExpressionSink extends DataFlow::ExprNode {
+ EvaluateExpressionSink() {
+ exists(MethodAccess ea, EvaluateExpressionMethod m | m = ea.getMethod() |
+ this.asExpr() = ea.getArgument(1) and // The second argument is the JavaScript or Java input
+ not exists(MethodAccess ca |
+ (
+ ca.getMethod().hasName("initSafeStandardObjects") // safe mode
+ or
+ ca.getMethod().hasName("setClassShutter") // `ClassShutter` constraint is enforced
+ ) and
+ ea.getQualifier() = ca.getQualifier().(VarAccess).getVariable().getAnAccess()
+ )
+ )
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.expected
new file mode 100644
index 00000000000..4d2736c8230
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.expected
@@ -0,0 +1,7 @@
+edges
+| RhinoServlet.java:25:23:25:50 | getParameter(...) : String | RhinoServlet.java:29:55:29:58 | code |
+nodes
+| RhinoServlet.java:25:23:25:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| RhinoServlet.java:29:55:29:58 | code | semmle.label | code |
+#select
+| RhinoServlet.java:29:55:29:58 | code | RhinoServlet.java:25:23:25:50 | getParameter(...) : String | RhinoServlet.java:29:55:29:58 | code | Rhino injection from $@. | RhinoServlet.java:25:23:25:50 | getParameter(...) | user input |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.qlref
new file mode 100644
index 00000000000..e306dda44df
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoInjection.qlref
@@ -0,0 +1 @@
+experimental/Security/CWE/CWE-094/RhinoInjection.ql
\ No newline at end of file
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
new file mode 100644
index 00000000000..f6f529785cc
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
@@ -0,0 +1,78 @@
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mozilla.javascript.ClassShutter;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.RhinoException;
+
+/**
+ * Servlet implementation class RhinoServlet
+ */
+public class RhinoServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public RhinoServlet() {
+ super();
+ }
+
+ // BAD: allow arbitrary Java and JavaScript code to be executed
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ Context ctx = Context.enter();
+ try {
+ Scriptable scope = ctx.initStandardObjects();
+ Object result = ctx.evaluateString(scope, code, "", 1, null);
+ response.getWriter().print(Context.toString(result));
+ } catch(RhinoException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ Context.exit();
+ }
+ }
+
+ // GOOD: enable the safe mode
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ Context ctx = Context.enter();
+ try {
+ Scriptable scope = ctx.initSafeStandardObjects();
+ Object result = ctx.evaluateString(scope, code, "", 1, null);
+ response.getWriter().print(Context.toString(result));
+ } catch(RhinoException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ Context.exit();
+ }
+ }
+
+ // GOOD: enforce a constraint on allowed classes
+ protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ String code = request.getParameter("code");
+ Context ctx = Context.enter();
+ try {
+ Scriptable scope = ctx.initStandardObjects();
+ ctx.setClassShutter(new ClassShutter() {
+ public boolean visibleToScripts(String className) {
+ if(className.startsWith("com.example.")) {
+ return true;
+ }
+ return false;
+ }
+ });
+
+ Object result = ctx.evaluateString(scope, code, "", 1, null);
+ response.getWriter().print(Context.toString(result));
+ } catch(RhinoException ex) {
+ response.getWriter().println(ex.getMessage());
+ } finally {
+ Context.exit();
+ }
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/options b/java/ql/test/experimental/query-tests/security/CWE-094/options
index 95bc9acaa08..48cc00e0a17 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/options
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/options
@@ -1,2 +1,2 @@
-//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.2.3:${testdir}/../../../../stubs/mvel2-2.4.7:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ClassShutter.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ClassShutter.java
new file mode 100644
index 00000000000..f425e08e966
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ClassShutter.java
@@ -0,0 +1,56 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+Embeddings that wish to filter Java classes that are visible to scripts
+through the LiveConnect, should implement this interface.
+
+@see Context#setClassShutter(ClassShutter)
+@since 1.5 Release 4
+@author Norris Boyd
+*/
+
+ public interface ClassShutter {
+
+ /**
+ * Return true iff the Java class with the given name should be exposed
+ * to scripts.
+ *
+ * An embedding may filter which Java classes are exposed through
+ * LiveConnect to JavaScript scripts.
+ *
+ * Due to the fact that there is no package reflection in Java,
+ * this method will also be called with package names. There
+ * is no way for Rhino to tell if "Packages.a.b" is a package name
+ * or a class that doesn't exist. What Rhino does is attempt
+ * to load each segment of "Packages.a.b.c": It first attempts to
+ * load class "a", then attempts to load class "a.b", then
+ * finally attempts to load class "a.b.c". On a Rhino installation
+ * without any ClassShutter set, and without any of the
+ * above classes, the expression "Packages.a.b.c" will result in
+ * a [JavaPackage a.b.c] and not an error.
+ *
+ * With ClassShutter supplied, Rhino will first call
+ * visibleToScripts before attempting to look up the class name. If
+ * visibleToScripts returns false, the class name lookup is not
+ * performed and subsequent Rhino execution assumes the class is
+ * not present. So for "java.lang.System.out.println" the lookup
+ * of "java.lang.System" is skipped and thus Rhino assumes that
+ * "java.lang.System" doesn't exist. So then for "java.lang.System.out",
+ * Rhino attempts to load the class "java.lang.System.out" because
+ * it assumes that "java.lang.System" is a package name.
+ *
+ * @param fullClassName the full name of the class (including the package
+ * name, with '.' as a delimiter). For example the
+ * standard string class is "java.lang.String"
+ * @return whether or not to reveal this class to scripts
+ */
+ public boolean visibleToScripts(String fullClassName);
+}
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Context.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Context.java
new file mode 100644
index 00000000000..57d30a3ab25
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Context.java
@@ -0,0 +1,623 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Locale;
+
+/**
+ * This class represents the runtime context of an executing script.
+ *
+ * Before executing a script, an instance of Context must be created
+ * and associated with the thread that will be executing the script.
+ * The Context will be used to store information about the executing
+ * of the script such as the call stack. Contexts are associated with
+ * the current thread using the {@link #call(ContextAction)}
+ * or {@link #enter()} methods.
+ *
+ * Different forms of script execution are supported. Scripts may be
+ * evaluated from the source directly, or first compiled and then later
+ * executed. Interactive execution is also supported.
+ *
+ * Some aspects of script execution, such as type conversions and
+ * object creation, may be accessed directly through methods of
+ * Context.
+ *
+ * @see Scriptable
+ * @author Norris Boyd
+ * @author Brendan Eich
+ */
+
+public class Context
+ implements Closeable
+{
+ /**
+ * Creates a new Context. The context will be associated with the {@link
+ * ContextFactory#getGlobal() global context factory}.
+ *
+ * Note that the Context must be associated with a thread before
+ * it can be used to execute a script.
+ * @deprecated this constructor is deprecated because it creates a
+ * dependency on a static singleton context factory. Use
+ * {@link ContextFactory#enter()} or
+ * {@link ContextFactory#call(ContextAction)} instead. If you subclass
+ * this class, consider using {@link #Context(ContextFactory)} constructor
+ * instead in the subclasses' constructors.
+ */
+ @Deprecated
+ public Context()
+ {
+ }
+
+ /**
+ * Creates a new context. Provided as a preferred super constructor for
+ * subclasses in place of the deprecated default public constructor.
+ * @param factory the context factory associated with this context (most
+ * likely, the one that created the context). Can not be null. The context
+ * features are inherited from the factory, and the context will also
+ * otherwise use its factory's services.
+ * @throws IllegalArgumentException if factory parameter is null.
+ */
+ protected Context(ContextFactory factory)
+ {
+ }
+
+ /**
+ * Get the current Context.
+ *
+ * The current Context is per-thread; this method looks up
+ * the Context associated with the current thread.
+ *
+ * @return the Context associated with the current thread, or
+ * null if no context is associated with the current
+ * thread.
+ * @see ContextFactory#enterContext()
+ * @see ContextFactory#call(ContextAction)
+ */
+ public static Context getCurrentContext()
+ {
+ return null;
+ }
+
+ /**
+ * Same as calling {@link ContextFactory#enterContext()} on the global
+ * ContextFactory instance.
+ * @return a Context associated with the current thread
+ * @see #getCurrentContext()
+ * @see #exit()
+ * @see #call(ContextAction)
+ */
+ public static Context enter()
+ {
+ return null;
+ }
+
+ /**
+ * Get a Context associated with the current thread, using
+ * the given Context if need be.
+ *
+ * The same as enter() except that cx
+ * is associated with the current thread and returned if
+ * the current thread has no associated context and cx
+ * is not associated with any other thread.
+ * @param cx a Context to associate with the thread if possible
+ * @return a Context associated with the current thread
+ * @deprecated use {@link ContextFactory#enterContext(Context)} instead as
+ * this method relies on usage of a static singleton "global" ContextFactory.
+ * @see ContextFactory#enterContext(Context)
+ * @see ContextFactory#call(ContextAction)
+ */
+ @Deprecated
+ public static Context enter(Context cx)
+ {
+ return null;
+ }
+
+ static final Context enter(Context cx, ContextFactory factory)
+ {
+ return null;
+ }
+
+ /**
+ * Exit a block of code requiring a Context.
+ *
+ * Calling exit() will remove the association between
+ * the current thread and a Context if the prior call to
+ * {@link ContextFactory#enterContext()} on this thread newly associated a
+ * Context with this thread. Once the current thread no longer has an
+ * associated Context, it cannot be used to execute JavaScript until it is
+ * again associated with a Context.
+ * @see ContextFactory#enterContext()
+ */
+ public static void exit()
+ {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ /**
+ * Return {@link ContextFactory} instance used to create this Context.
+ */
+ public final ContextFactory getFactory()
+ {
+ return null;
+ }
+
+ /**
+ * Checks if this is a sealed Context. A sealed Context instance does not
+ * allow to modify any of its properties and will throw an exception
+ * on any such attempt.
+ * @see #seal(Object sealKey)
+ */
+ public final boolean isSealed()
+ {
+ return false;
+ }
+
+ /**
+ * Seal this Context object so any attempt to modify any of its properties
+ * including calling {@link #enter()} and {@link #exit()} methods will
+ * throw an exception.
+ *
+ * If sealKey is not null, calling
+ * {@link #unseal(Object sealKey)} with the same key unseals
+ * the object. If sealKey is null, unsealing is no longer possible.
+ *
+ * @see #isSealed()
+ * @see #unseal(Object)
+ */
+ public final void seal(Object sealKey)
+ {
+ }
+
+ /**
+ * Unseal previously sealed Context object.
+ * The sealKey argument should not be null and should match
+ * sealKey suplied with the last call to
+ * {@link #seal(Object)} or an exception will be thrown.
+ *
+ * @see #isSealed()
+ * @see #seal(Object sealKey)
+ */
+ public final void unseal(Object sealKey)
+ {
+ }
+
+ /**
+ * Get the current language version.
+ *
+ * The language version number affects JavaScript semantics as detailed
+ * in the overview documentation.
+ *
+ * @return an integer that is one of VERSION_1_0, VERSION_1_1, etc.
+ */
+ public final int getLanguageVersion()
+ {
+ return -1;
+ }
+
+ /**
+ * Set the language version.
+ *
+ *
+ * Setting the language version will affect functions and scripts compiled
+ * subsequently. See the overview documentation for version-specific
+ * behavior.
+ *
+ * @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
+ */
+ public void setLanguageVersion(int version)
+ {
+ }
+
+ public static boolean isValidLanguageVersion(int version)
+ {
+ return false;
+ }
+
+ public static void checkLanguageVersion(int version)
+ {
+ }
+
+ /**
+ * Get the implementation version.
+ *
+ *
+ * The implementation version is of the form
+ *
+ * "name langVerreleaserelNum date"
+ *
+ * where name is the name of the product, langVer is
+ * the language version, relNum is the release number, and
+ * date is the release date for that specific
+ * release in the form "yyyy mm dd".
+ *
+ * @return a string that encodes the product, language version, release
+ * number, and date.
+ */
+ public final String getImplementationVersion() {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * @return the initialized scope
+ */
+ public final ScriptableObject initStandardObjects()
+ {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects, leaving out those that offer access directly
+ * to Java classes. This sets up "scope" to have access to all the standard
+ * JavaScript classes, but does not create global objects for any top-level
+ * Java packages. In addition, the "Packages," "JavaAdapter," and
+ * "JavaImporter" classes, and the "getClass" function, are not
+ * initialized.
+ *
+ * The result of this function is a scope that may be safely used in a "sandbox"
+ * environment where it is not desirable to give access to Java code from JavaScript.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * @return the initialized scope
+ */
+ public final ScriptableObject initSafeStandardObjects()
+ {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * @param scope the scope to initialize, or null, in which case a new
+ * object will be created to serve as the scope
+ * @return the initialized scope. The method returns the value of the scope
+ * argument if it is not null or newly allocated scope object which
+ * is an instance {@link ScriptableObject}.
+ */
+ public final Scriptable initStandardObjects(ScriptableObject scope)
+ {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects, leaving out those that offer access directly
+ * to Java classes. This sets up "scope" to have access to all the standard
+ * JavaScript classes, but does not create global objects for any top-level
+ * Java packages. In addition, the "Packages," "JavaAdapter," and
+ * "JavaImporter" classes, and the "getClass" function, are not
+ * initialized.
+ *
+ * The result of this function is a scope that may be safely used in a "sandbox"
+ * environment where it is not desirable to give access to Java code from JavaScript.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * @param scope the scope to initialize, or null, in which case a new
+ * object will be created to serve as the scope
+ * @return the initialized scope. The method returns the value of the scope
+ * argument if it is not null or newly allocated scope object which
+ * is an instance {@link ScriptableObject}.
+ */
+ public final Scriptable initSafeStandardObjects(ScriptableObject scope)
+ {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * This form of the method also allows for creating "sealed" standard
+ * objects. An object that is sealed cannot have properties added, changed,
+ * or removed. This is useful to create a "superglobal" that can be shared
+ * among several top-level objects. Note that sealing is not allowed in
+ * the current ECMA/ISO language specification, but is likely for
+ * the next version.
+ *
+ * @param scope the scope to initialize, or null, in which case a new
+ * object will be created to serve as the scope
+ * @param sealed whether or not to create sealed standard objects that
+ * cannot be modified.
+ * @return the initialized scope. The method returns the value of the scope
+ * argument if it is not null or newly allocated scope object.
+ * @since 1.4R3
+ */
+ public ScriptableObject initStandardObjects(ScriptableObject scope,
+ boolean sealed)
+ {
+ return null;
+ }
+
+ /**
+ * Initialize the standard objects, leaving out those that offer access directly
+ * to Java classes. This sets up "scope" to have access to all the standard
+ * JavaScript classes, but does not create global objects for any top-level
+ * Java packages. In addition, the "Packages," "JavaAdapter," and
+ * "JavaImporter" classes, and the "getClass" function, are not
+ * initialized.
+ *
+ * The result of this function is a scope that may be safely used in a "sandbox"
+ * environment where it is not desirable to give access to Java code from JavaScript.
+ *
+ * Creates instances of the standard objects and their constructors
+ * (Object, String, Number, Date, etc.), setting up 'scope' to act
+ * as a global object as in ECMA 15.1.
+ *
+ * This method must be called to initialize a scope before scripts
+ * can be evaluated in that scope.
+ *
+ * This method does not affect the Context it is called upon.
+ *
+ * This form of the method also allows for creating "sealed" standard
+ * objects. An object that is sealed cannot have properties added, changed,
+ * or removed. This is useful to create a "superglobal" that can be shared
+ * among several top-level objects. Note that sealing is not allowed in
+ * the current ECMA/ISO language specification, but is likely for
+ * the next version.
+ *
+ * @param scope the scope to initialize, or null, in which case a new
+ * object will be created to serve as the scope
+ * @param sealed whether or not to create sealed standard objects that
+ * cannot be modified.
+ * @return the initialized scope. The method returns the value of the scope
+ * argument if it is not null or newly allocated scope object.
+ * @since 1.7.6
+ */
+ public ScriptableObject initSafeStandardObjects(ScriptableObject scope,
+ boolean sealed)
+ {
+ return null;
+ }
+
+ /**
+ * Get the singleton object that represents the JavaScript Undefined value.
+ */
+ public static Object getUndefinedValue()
+ {
+ return null;
+ }
+
+ /**
+ * Evaluate a JavaScript source string.
+ *
+ * The provided source name and line number are used for error messages
+ * and for producing debug information.
+ *
+ * @param scope the scope to execute in
+ * @param source the JavaScript source
+ * @param sourceName a string describing the source, such as a filename
+ * @param lineno the starting line number
+ * @param securityDomain an arbitrary object that specifies security
+ * information about the origin or owner of the script. For
+ * implementations that don't care about security, this value
+ * may be null.
+ * @return the result of evaluating the string
+ * @see org.mozilla.javascript.SecurityController
+ */
+ public final Object evaluateString(Scriptable scope, String source,
+ String sourceName, int lineno,
+ Object securityDomain)
+ {
+ return null;
+ }
+
+ /**
+ * Evaluate a reader as JavaScript source.
+ *
+ * All characters of the reader are consumed.
+ *
+ * @param scope the scope to execute in
+ * @param in the Reader to get JavaScript source from
+ * @param sourceName a string describing the source, such as a filename
+ * @param lineno the starting line number
+ * @param securityDomain an arbitrary object that specifies security
+ * information about the origin or owner of the script. For
+ * implementations that don't care about security, this value
+ * may be null.
+ * @return the result of evaluating the source
+ *
+ * @exception IOException if an IOException was generated by the Reader
+ */
+ public final Object evaluateReader(Scriptable scope, Reader in,
+ String sourceName, int lineno,
+ Object securityDomain)
+ throws IOException
+ {
+ return null;
+ }
+
+ /**
+ * Convert the value to a JavaScript boolean value.
+ *
+ * See ECMA 9.2.
+ *
+ * @param value a JavaScript value
+ * @return the corresponding boolean value converted using
+ * the ECMA rules
+ */
+ public static boolean toBoolean(Object value)
+ {
+ return false;
+ }
+
+ /**
+ * Convert the value to a JavaScript Number value.
+ *
+ * Returns a Java double for the JavaScript Number.
+ *
+ * See ECMA 9.3.
+ *
+ * @param value a JavaScript value
+ * @return the corresponding double value converted using
+ * the ECMA rules
+ */
+ public static double toNumber(Object value)
+ {
+ return -1;
+ }
+
+ /**
+ * Convert the value to a JavaScript String value.
+ *
+ * See ECMA 9.8.
+ *
+ * @param value a JavaScript value
+ * @return the corresponding String value converted using
+ * the ECMA rules
+ */
+ public static String toString(Object value)
+ {
+ return null;
+ }
+
+ /**
+ * Convert the value to an JavaScript object value.
+ *
+ * Note that a scope must be provided to look up the constructors
+ * for Number, Boolean, and String.
+ *
+ * See ECMA 9.9.
+ *
+ * Additionally, arbitrary Java objects and classes will be
+ * wrapped in a Scriptable object with its Java fields and methods
+ * reflected as JavaScript properties of the object.
+ *
+ * @param value any Java object
+ * @param scope global scope containing constructors for Number,
+ * Boolean, and String
+ * @return new JavaScript object
+ */
+ public static Scriptable toObject(Object value, Scriptable scope)
+ {
+ return null;
+ }
+
+ /**
+ * Convenient method to convert java value to its closest representation
+ * in JavaScript.
+ *
+ * If value is an instance of String, Number, Boolean, Function or
+ * Scriptable, it is returned as it and will be treated as the corresponding
+ * JavaScript type of string, number, boolean, function and object.
+ *
+ * Note that for Number instances during any arithmetic operation in
+ * JavaScript the engine will always use the result of
+ * Number.doubleValue() resulting in a precision loss if
+ * the number can not fit into double.
+ *
+ * If value is an instance of Character, it will be converted to string of
+ * length 1 and its JavaScript type will be string.
+ *
+ * The rest of values will be wrapped as LiveConnect objects
+ * by calling {@link WrapFactory#wrap(Context cx, Scriptable scope,
+ * Object obj, Class staticType)} as in:
+ *
+ *
+ * @param value any Java object
+ * @param scope top scope object
+ * @return value suitable to pass to any API that takes JavaScript values.
+ */
+ public static Object javaToJS(Object value, Scriptable scope)
+ {
+ return null;
+ }
+
+ /**
+ * Convert a JavaScript value into the desired type.
+ * Uses the semantics defined with LiveConnect3 and throws an
+ * Illegal argument exception if the conversion cannot be performed.
+ * @param value the JavaScript value to convert
+ * @param desiredType the Java type to convert to. Primitive Java
+ * types are represented using the TYPE fields in the corresponding
+ * wrapper class in java.lang.
+ * @return the converted value
+ * @throws EvaluatorException if the conversion cannot be performed
+ */
+ public static Object jsToJava(Object value, Class> desiredType)
+ {
+ return null;
+ }
+
+ /**
+ * Set the LiveConnect access filter for this context.
+ *
{@link ClassShutter} may only be set if it is currently null.
+ * Otherwise a SecurityException is thrown.
+ * @param shutter a ClassShutter object
+ * @throws SecurityException if there is already a ClassShutter
+ * object for this Context
+ */
+ public synchronized final void setClassShutter(ClassShutter shutter)
+ {
+ }
+
+ final synchronized ClassShutter getClassShutter()
+ {
+ return null;
+ }
+
+ public interface ClassShutterSetter {
+ public void setClassShutter(ClassShutter shutter);
+ public ClassShutter getClassShutter();
+ }
+
+ public final synchronized ClassShutterSetter getClassShutterSetter() {
+ return null;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ContextFactory.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ContextFactory.java
new file mode 100644
index 00000000000..a7f83f2095d
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ContextFactory.java
@@ -0,0 +1,314 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * Factory class that Rhino runtime uses to create new {@link Context}
+ * instances. A ContextFactory can also notify listeners
+ * about context creation and release.
+ *
+ * When the Rhino runtime needs to create new {@link Context} instance during
+ * execution of {@link Context#enter()} or {@link Context}, it will call
+ * {@link #makeContext()} of the current global ContextFactory.
+ * See {@link #getGlobal()} and {@link #initGlobal(ContextFactory)}.
+ *
+ * It is also possible to use explicit ContextFactory instances for Context
+ * creation. This is useful to have a set of independent Rhino runtime
+ * instances under single JVM. See {@link #call(ContextAction)}.
+ *
+ * The following example demonstrates Context customization to terminate
+ * scripts running more then 10 seconds and to provide better compatibility
+ * with JavaScript code using MSIE-specific features.
+ *
+ * import org.mozilla.javascript.*;
+ *
+ * class MyFactory extends ContextFactory
+ * {
+ *
+ * // Custom {@link Context} to store execution time.
+ * private static class MyContext extends Context
+ * {
+ * long startTime;
+ * }
+ *
+ * static {
+ * // Initialize GlobalFactory with custom factory
+ * ContextFactory.initGlobal(new MyFactory());
+ * }
+ *
+ * // Override {@link #makeContext()}
+ * protected Context makeContext()
+ * {
+ * MyContext cx = new MyContext();
+ * // Make Rhino runtime to call observeInstructionCount
+ * // each 10000 bytecode instructions
+ * cx.setInstructionObserverThreshold(10000);
+ * return cx;
+ * }
+ *
+ * // Override {@link #hasFeature(Context, int)}
+ * public boolean hasFeature(Context cx, int featureIndex)
+ * {
+ * // Turn on maximum compatibility with MSIE scripts
+ * switch (featureIndex) {
+ * case {@link Context#FEATURE_NON_ECMA_GET_YEAR}:
+ * return true;
+ *
+ * case {@link Context#FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME}:
+ * return true;
+ *
+ * case {@link Context#FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER}:
+ * return true;
+ *
+ * case {@link Context#FEATURE_PARENT_PROTO_PROPERTIES}:
+ * return false;
+ * }
+ * return super.hasFeature(cx, featureIndex);
+ * }
+ *
+ * // Override {@link #observeInstructionCount(Context, int)}
+ * protected void observeInstructionCount(Context cx, int instructionCount)
+ * {
+ * MyContext mcx = (MyContext)cx;
+ * long currentTime = System.currentTimeMillis();
+ * if (currentTime - mcx.startTime > 10*1000) {
+ * // More then 10 seconds from Context creation time:
+ * // it is time to stop the script.
+ * // Throw Error instance to ensure that script will never
+ * // get control back through catch or finally.
+ * throw new Error();
+ * }
+ * }
+ *
+ * // Override {@link #doTopCall(Callable,
+ Context, Scriptable,
+ Scriptable, Object[])}
+ * protected Object doTopCall(Callable callable,
+ * Context cx, Scriptable scope,
+ * Scriptable thisObj, Object[] args)
+ * {
+ * MyContext mcx = (MyContext)cx;
+ * mcx.startTime = System.currentTimeMillis();
+ *
+ * return super.doTopCall(callable, cx, scope, thisObj, args);
+ * }
+ *
+ * }
+ *
+ */
+
+public class ContextFactory
+{
+
+ /**
+ * Listener of {@link Context} creation and release events.
+ */
+ public interface Listener
+ {
+ /**
+ * Notify about newly created {@link Context} object.
+ */
+ public void contextCreated(Context cx);
+
+ /**
+ * Notify that the specified {@link Context} instance is no longer
+ * associated with the current thread.
+ */
+ public void contextReleased(Context cx);
+ }
+
+ /**
+ * Get global ContextFactory.
+ *
+ * @see #hasExplicitGlobal()
+ * @see #initGlobal(ContextFactory)
+ */
+ public static ContextFactory getGlobal()
+ {
+ return null;
+ }
+
+ /**
+ * Check if global factory was set.
+ * Return true to indicate that {@link #initGlobal(ContextFactory)} was
+ * already called and false to indicate that the global factory was not
+ * explicitly set.
+ *
+ * @see #getGlobal()
+ * @see #initGlobal(ContextFactory)
+ */
+ public static boolean hasExplicitGlobal()
+ {
+ return false;
+ }
+
+ /**
+ * Set global ContextFactory.
+ * The method can only be called once.
+ *
+ * @see #getGlobal()
+ * @see #hasExplicitGlobal()
+ */
+ public synchronized static void initGlobal(ContextFactory factory)
+ {
+ }
+
+ public interface GlobalSetter {
+ public void setContextFactoryGlobal(ContextFactory factory);
+ public ContextFactory getContextFactoryGlobal();
+ }
+
+ public synchronized static GlobalSetter getGlobalSetter() {
+ return null;
+ }
+
+ /**
+ * Create new {@link Context} instance to be associated with the current
+ * thread.
+ * This is a callback method used by Rhino to create {@link Context}
+ * instance when it is necessary to associate one with the current
+ * execution thread. makeContext() is allowed to call
+ * {@link Context#seal(Object)} on the result to prevent
+ * {@link Context} changes by hostile scripts or applets.
+ */
+ protected Context makeContext()
+ {
+ return null;
+ }
+
+ /**
+ * Implementation of {@link Context#hasFeature(int featureIndex)}.
+ * This can be used to customize {@link Context} without introducing
+ * additional subclasses.
+ */
+ protected boolean hasFeature(Context cx, int featureIndex)
+ {
+ return false;
+ }
+
+ /**
+ * Get ClassLoader to use when searching for Java classes.
+ * Unless it was explicitly initialized with
+ * {@link #initApplicationClassLoader(ClassLoader)} the method returns
+ * null to indicate that Thread.getContextClassLoader() should be used.
+ */
+ public final ClassLoader getApplicationClassLoader()
+ {
+ return null;
+ }
+
+ /**
+ * Set explicit class loader to use when searching for Java classes.
+ *
+ * @see #getApplicationClassLoader()
+ */
+ public final void initApplicationClassLoader(ClassLoader loader)
+ {
+ }
+
+ /**
+ * Checks if this is a sealed ContextFactory.
+ * @see #seal()
+ */
+ public final boolean isSealed()
+ {
+ return false;
+ }
+
+ /**
+ * Seal this ContextFactory so any attempt to modify it like to add or
+ * remove its listeners will throw an exception.
+ * @see #isSealed()
+ */
+ public final void seal()
+ {
+ }
+
+ /**
+ * Get a context associated with the current thread, creating one if need
+ * be. The Context stores the execution state of the JavaScript engine, so
+ * it is required that the context be entered before execution may begin.
+ * Once a thread has entered a Context, then getCurrentContext() may be
+ * called to find the context that is associated with the current thread.
+ *
+ * Calling enterContext() will return either the Context
+ * currently associated with the thread, or will create a new context and
+ * associate it with the current thread. Each call to
+ * enterContext() must have a matching call to
+ * {@link Context#exit()}.
+ *
+ * Instead of using enterContext(), exit() pair consider
+ * using {@link #call(ContextAction)} which guarantees proper association
+ * of Context instances with the current thread.
+ * With this method the above example becomes:
+ *
+ * @return a Context associated with the current thread
+ * @see Context#getCurrentContext()
+ * @see Context#exit()
+ * @see #call(ContextAction)
+ */
+ public Context enterContext()
+ {
+ return null;
+ }
+
+ /**
+ * @deprecated use {@link #enterContext()} instead
+ * @return a Context associated with the current thread
+ */
+ @Deprecated
+ public final Context enter()
+ {
+ return null;
+ }
+
+ /**
+ * @deprecated Use {@link Context#exit()} instead.
+ */
+ @Deprecated
+ public final void exit()
+ {
+ }
+
+ /**
+ * Get a Context associated with the current thread, using the given
+ * Context if need be.
+ *
+ * The same as enterContext() except that cx
+ * is associated with the current thread and returned if the current thread
+ * has no associated context and cx is not associated with any
+ * other thread.
+ * @param cx a Context to associate with the thread if possible
+ * @return a Context associated with the current thread
+ * @see #enterContext()
+ * @see #call(ContextAction)
+ * @throws IllegalStateException if cx is already associated
+ * with a different thread
+ */
+ public final Context enterContext(Context cx)
+ {
+ return null;
+ }
+}
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/RhinoException.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/RhinoException.java
new file mode 100644
index 00000000000..b11befb4a63
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/RhinoException.java
@@ -0,0 +1,15 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+
+package org.mozilla.javascript;
+
+/**
+ * The class of exceptions thrown by the JavaScript engine.
+ */
+public abstract class RhinoException extends RuntimeException
+{
+}
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Scriptable.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Scriptable.java
new file mode 100644
index 00000000000..34616f7ad74
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Scriptable.java
@@ -0,0 +1,304 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is interface that all objects in JavaScript must implement.
+ * The interface provides for the management of properties and for
+ * performing conversions.
+ *
+ * Host system implementors may find it easier to extend the ScriptableObject
+ * class rather than implementing Scriptable when writing host objects.
+ *
+ * There are many static methods defined in ScriptableObject that perform
+ * the multiple calls to the Scriptable interface needed in order to
+ * manipulate properties in prototype chains.
+ *
+ *
+ * @see org.mozilla.javascript.ScriptableObject
+ * @author Norris Boyd
+ * @author Nick Thompson
+ * @author Brendan Eich
+ */
+
+public interface Scriptable {
+
+ /**
+ * Get the name of the set of objects implemented by this Java class.
+ * This corresponds to the [[Class]] operation in ECMA and is used
+ * by Object.prototype.toString() in ECMA.
+ * See ECMA 8.6.2 and 15.2.4.2.
+ */
+ public String getClassName();
+
+ /**
+ * Get a named property from the object.
+ *
+ * Looks property up in this object and returns the associated value
+ * if found. Returns NOT_FOUND if not found.
+ * Note that this method is not expected to traverse the prototype
+ * chain. This is different from the ECMA [[Get]] operation.
+ *
+ * Depending on the property selector, the runtime will call
+ * this method or the form of get that takes an
+ * integer:
+ *
+ *
JavaScript code
Java code
+ *
a.b
a.get("b", a)
+ *
a["foo"]
a.get("foo", a)
+ *
a[3]
a.get(3, a)
+ *
a["3"]
a.get(3, a)
+ *
a[3.0]
a.get(3, a)
+ *
a["3.0"]
a.get("3.0", a)
+ *
a[1.1]
a.get("1.1", a)
+ *
a[-4]
a.get(-4, a)
+ *
+ *
+ * The values that may be returned are limited to the following:
+ *
+ *
java.lang.Boolean objects
+ *
java.lang.String objects
+ *
java.lang.Number objects
+ *
org.mozilla.javascript.Scriptable objects
+ *
null
+ *
The value returned by Context.getUndefinedValue()
+ *
NOT_FOUND
+ *
+ * @param name the name of the property
+ * @param start the object in which the lookup began
+ * @return the value of the property (may be null), or NOT_FOUND
+ * @see org.mozilla.javascript.Context#getUndefinedValue
+ */
+ public Object get(String name, Scriptable start);
+
+ /**
+ * Get a property from the object selected by an integral index.
+ *
+ * Identical to get(String, Scriptable) except that
+ * an integral index is used to select the property.
+ *
+ * @param index the numeric index for the property
+ * @param start the object in which the lookup began
+ * @return the value of the property (may be null), or NOT_FOUND
+ * @see org.mozilla.javascript.Scriptable#get(String,Scriptable)
+ */
+ public Object get(int index, Scriptable start);
+
+ /**
+ * Indicates whether or not a named property is defined in an object.
+ *
+ * Does not traverse the prototype chain.
+ *
+ * The property is specified by a String name
+ * as defined for the get method.
+ *
+ * @param name the name of the property
+ * @param start the object in which the lookup began
+ * @return true if and only if the named property is found in the object
+ * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, String)
+ */
+ public boolean has(String name, Scriptable start);
+
+ /**
+ * Indicates whether or not an indexed property is defined in an object.
+ *
+ * Does not traverse the prototype chain.
+ *
+ * The property is specified by an integral index
+ * as defined for the get method.
+ *
+ * @param index the numeric index for the property
+ * @param start the object in which the lookup began
+ * @return true if and only if the indexed property is found in the object
+ * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#getProperty(Scriptable, int)
+ */
+ public boolean has(int index, Scriptable start);
+
+ /**
+ * Sets a named property in this object.
+ *
+ * The property is specified by a string name
+ * as defined for get.
+ *
+ * The possible values that may be passed in are as defined for
+ * get. A class that implements this method may choose
+ * to ignore calls to set certain properties, in which case those
+ * properties are effectively read-only.
+ * For properties defined in a prototype chain,
+ * use putProperty in ScriptableObject.
+ * Note that if a property a is defined in the prototype p
+ * of an object o, then evaluating o.a = 23 will cause
+ * set to be called on the prototype p with
+ * o as the start parameter.
+ * To preserve JavaScript semantics, it is the Scriptable
+ * object's responsibility to modify o.
+ * This design allows properties to be defined in prototypes and implemented
+ * in terms of getters and setters of Java values without consuming slots
+ * in each instance.
+ *
+ * The values that may be set are limited to the following:
+ *
+ *
java.lang.Boolean objects
+ *
java.lang.String objects
+ *
java.lang.Number objects
+ *
org.mozilla.javascript.Scriptable objects
+ *
null
+ *
The value returned by Context.getUndefinedValue()
+ *
+ * Arbitrary Java objects may be wrapped in a Scriptable by first calling
+ * Context.toObject. This allows the property of a JavaScript
+ * object to contain an arbitrary Java object as a value.
+ * Note that has will be called by the runtime first before
+ * set is called to determine in which object the
+ * property is defined.
+ * Note that this method is not expected to traverse the prototype chain,
+ * which is different from the ECMA [[Put]] operation.
+ * @param name the name of the property
+ * @param start the object whose property is being set
+ * @param value value to set the property to
+ * @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
+ * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, String, Object)
+ * @see org.mozilla.javascript.Context#toObject(Object, Scriptable)
+ */
+ public void put(String name, Scriptable start, Object value);
+
+ /**
+ * Sets an indexed property in this object.
+ *
+ * The property is specified by an integral index
+ * as defined for get.
+ *
+ * Identical to put(String, Scriptable, Object) except that
+ * an integral index is used to select the property.
+ *
+ * @param index the numeric index for the property
+ * @param start the object whose property is being set
+ * @param value value to set the property to
+ * @see org.mozilla.javascript.Scriptable#has(int, Scriptable)
+ * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#putProperty(Scriptable, int, Object)
+ * @see org.mozilla.javascript.Context#toObject(Object, Scriptable)
+ */
+ public void put(int index, Scriptable start, Object value);
+
+ /**
+ * Removes a property from this object.
+ * This operation corresponds to the ECMA [[Delete]] except that
+ * the no result is returned. The runtime will guarantee that this
+ * method is called only if the property exists. After this method
+ * is called, the runtime will call Scriptable.has to see if the
+ * property has been removed in order to determine the boolean
+ * result of the delete operator as defined by ECMA 11.4.1.
+ *
+ * A property can be made permanent by ignoring calls to remove
+ * it.
+ * The property is specified by a String name
+ * as defined for get.
+ *
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
+ * @param name the identifier for the property
+ * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, String)
+ */
+ public void delete(String name);
+
+ /**
+ * Removes a property from this object.
+ *
+ * The property is specified by an integral index
+ * as defined for get.
+ *
+ * To delete properties defined in a prototype chain,
+ * see deleteProperty in ScriptableObject.
+ *
+ * Identical to delete(String) except that
+ * an integral index is used to select the property.
+ *
+ * @param index the numeric index for the property
+ * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
+ * @see org.mozilla.javascript.ScriptableObject#deleteProperty(Scriptable, int)
+ */
+ public void delete(int index);
+
+ /**
+ * Get the prototype of the object.
+ * @return the prototype
+ */
+ public Scriptable getPrototype();
+
+ /**
+ * Set the prototype of the object.
+ * @param prototype the prototype to set
+ */
+ public void setPrototype(Scriptable prototype);
+
+ /**
+ * Get the parent scope of the object.
+ * @return the parent scope
+ */
+ public Scriptable getParentScope();
+
+ /**
+ * Set the parent scope of the object.
+ * @param parent the parent scope to set
+ */
+ public void setParentScope(Scriptable parent);
+
+ /**
+ * Get an array of property ids.
+ *
+ * Not all property ids need be returned. Those properties
+ * whose ids are not returned are considered non-enumerable.
+ *
+ * @return an array of Objects. Each entry in the array is either
+ * a java.lang.String or a java.lang.Number
+ */
+ public Object[] getIds();
+
+ /**
+ * Get the default value of the object with a given hint.
+ * The hints are String.class for type String, Number.class for type
+ * Number, Scriptable.class for type Object, and Boolean.class for
+ * type Boolean.
+ *
+ * A hint of null means "no hint".
+ *
+ * See ECMA 8.6.2.6.
+ *
+ * @param hint the type hint
+ * @return the default value
+ */
+ public Object getDefaultValue(Class> hint);
+
+ /**
+ * The instanceof operator.
+ *
+ *
+ * The JavaScript code "lhs instanceof rhs" causes rhs.hasInstance(lhs) to
+ * be called.
+ *
+ *
+ * The return value is implementation dependent so that embedded host objects can
+ * return an appropriate value. See the JS 1.3 language documentation for more
+ * detail.
+ *
+ *
This operator corresponds to the proposed EMCA [[HasInstance]] operator.
+ *
+ * @param instance The value that appeared on the LHS of the instanceof
+ * operator
+ *
+ * @return an implementation dependent value
+ */
+ public boolean hasInstance(Scriptable instance);
+}
+
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ScriptableObject.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ScriptableObject.java
new file mode 100644
index 00000000000..298c4fc7fb0
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/ScriptableObject.java
@@ -0,0 +1,27 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is the default implementation of the Scriptable interface. This
+ * class provides convenient default behavior that makes it easier to
+ * define host objects.
+ *
+ * Various properties and methods of JavaScript objects can be conveniently
+ * defined using methods of ScriptableObject.
+ *
-Rhino is a JavaScript engine written fully in Java and managed by the Mozilla Foundation.
-It serves as an embedded scripting engine inside Java applications which allows
-Java-to-JavaScript interoperability and provides a seamless integration between the two
-languages. If an expression is built using attacker-controlled data, and then evaluated in
-a powerful context, it may allow the attacker to run arbitrary code.
-
-
-Typically an expression is evaluated in the powerful context initialized with
-initStandardObjects that allows an expression of arbitrary Java code to
-execute in the JVM.
-
-
-
-
-
-In general, including user input in a Rhino expression should be avoided.
-If user input must be included in the expression, it should be then evaluated in a safe
-context that doesn't allow arbitrary code invocation.
-
-
-
-
-
-The following example shows two ways of using Rhino expression. In the 'BAD' case,
-an unsafe context is initialized with initStandardObjects. In the 'GOOD' case,
-a safe context is initialized with initSafeStandardObjects or
-setClassShutter.
-
-
-
\ No newline at end of file
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql
deleted file mode 100644
index cac41244aa2..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.ql
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * @name Injection in Mozilla Rhino JavaScript Engine
- * @description Evaluation of a user-controlled JavaScript or Java expression in Rhino
- * JavaScript Engine may lead to remote code execution.
- * @kind path-problem
- * @id java/rhino-injection
- * @tags security
- * external/cwe/cwe-094
- */
-
-import java
-import RhinoInjection
-import DataFlow::PathGraph
-
-from DataFlow::PathNode source, DataFlow::PathNode sink, RhinoInjectionConfig conf
-where conf.hasFlowPath(source, sink)
-select sink.getNode(), source, sink, "Rhino injection from $@.", source.getNode(), " user input"
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll
deleted file mode 100644
index a560e340e85..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.qll
+++ /dev/null
@@ -1,56 +0,0 @@
-import java
-import semmle.code.java.dataflow.FlowSources
-import semmle.code.java.dataflow.TaintTracking
-
-/** The class `org.mozilla.javascript.Context`. */
-class Context extends RefType {
- Context() { this.hasQualifiedName("org.mozilla.javascript", "Context") }
-}
-
-/**
- * A method that evaluates a Rhino expression.
- */
-class EvaluateExpressionMethod extends Method {
- EvaluateExpressionMethod() {
- this.getDeclaringType().getAnAncestor*() instanceof Context and
- (
- hasName("evaluateString") or
- hasName("evaluateReader")
- )
- }
-}
-
-/**
- * A taint-tracking configuration for unsafe user input that is used to evaluate
- * a Rhino expression.
- */
-class RhinoInjectionConfig extends TaintTracking::Configuration {
- RhinoInjectionConfig() { this = "RhinoInjectionConfig" }
-
- override predicate isSource(DataFlow::Node source) {
- source instanceof RemoteFlowSource
- or
- source instanceof LocalUserInput
- }
-
- override predicate isSink(DataFlow::Node sink) { sink instanceof EvaluateExpressionSink }
-}
-
-/**
- * A sink for Rhino code injection vulnerabilities.
- */
-class EvaluateExpressionSink extends DataFlow::ExprNode {
- EvaluateExpressionSink() {
- exists(MethodAccess ea, EvaluateExpressionMethod m | m = ea.getMethod() |
- this.asExpr() = ea.getArgument(1) and // The second argument is the JavaScript or Java input
- not exists(MethodAccess ca |
- (
- ca.getMethod().hasName("initSafeStandardObjects") // safe mode
- or
- ca.getMethod().hasName("setClassShutter") // `ClassShutter` constraint is enforced
- ) and
- ea.getQualifier() = ca.getQualifier().(VarAccess).getVariable().getAnAccess()
- )
- )
- }
-}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptEngine.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptEngine.qhelp
deleted file mode 100644
index 74159c562c5..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptEngine.qhelp
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
The ScriptEngine API has been available since the release of Java 6.
-It allows applications to interact with scripts written in languages such as JavaScript.
-
-
-
-
Use "Cloudbees Rhino Sandbox" or sandboxing with SecurityManager or use graalvm instead.
-
-
-
-
The following code could execute random JavaScript code
The JavaScript Engine API has been available since the release of Java 6, which allows
+ applications to interact with scripts written in languages such as JavaScript. It serves
+ as an embedded scripting engine inside Java applications which allows Java-to-JavaScript
+ interoperability and provides a seamless integration between the two languages. If an
+ expression is built using attacker-controlled data, and then evaluated in a powerful
+ context, it may allow the attacker to run arbitrary code.
+
+
+
+
In general, including user input in a JavaScript Engine expression should be avoided.
+ If user input must be included in the expression, it should be then evaluated in a safe
+ context that doesn't allow arbitrary code invocation. Use "Cloudbees Rhino Sandbox" or
+ sandboxing with SecurityManager or use graalvm
+ instead.
+
+
+
+
The following code could execute random JavaScript code in ScriptEngine
+
+
+
+
The following example shows two ways of using Rhino expression. In the 'BAD' case,
+ an unsafe context is initialized with initStandardObjects that allows arbitrary
+ Java code to be executed. In the 'GOOD' case, a safe context is initialized with
+ initSafeStandardObjects or setClassShutter.
The JavaScript Engine API has been available since the release of Java 6, which allows
+
The Java Scripting API has been available since the release of Java 6, which allows
applications to interact with scripts written in languages such as JavaScript. It serves
as an embedded scripting engine inside Java applications which allows Java-to-JavaScript
interoperability and provides a seamless integration between the two languages. If an
@@ -13,11 +13,11 @@
-
In general, including user input in a JavaScript Engine expression should be avoided.
+
In general, including user input in a Java Script Engine expression should be avoided.
If user input must be included in the expression, it should be then evaluated in a safe
- context that doesn't allow arbitrary code invocation. Use "Cloudbees Rhino Sandbox" or
- sandboxing with SecurityManager or use graalvm
- instead.
+ context that doesn't allow arbitrary code invocation. Use "Cloudbees Rhino Sandbox" or
+ sandboxing with SecurityManager, which will be deprecated in a future release, or use
+ GraalVM instead.
Returns a script that may later be executed. Will consume all the source in the reader.
+ *
+ * @param in the input reader
+ * @param sourceName a string describing the source, such as a filename
+ * @param lineno the starting line number for reporting errors
+ * @param securityDomain an arbitrary object that specifies security information about the
+ * origin or owner of the script. For implementations that don't care about security, this
+ * value may be null.
+ * @return a script that may later be executed
+ * @exception IOException if an IOException was generated by the Reader
+ * @see org.mozilla.javascript.Script
+ */
+ public final Script compileReader(
+ Reader in, String sourceName, int lineno, Object securityDomain) throws IOException {
+ return null;
+ }
+
+ /**
+ * Compiles the source in the given string.
+ *
+ *
Returns a script that may later be executed.
+ *
+ * @param source the source string
+ * @param sourceName a string describing the source, such as a filename
+ * @param lineno the starting line number for reporting errors. Use 0 if the line number is
+ * unknown.
+ * @param securityDomain an arbitrary object that specifies security information about the
+ * origin or owner of the script. For implementations that don't care about security, this
+ * value may be null.
+ * @return a script that may later be executed
+ * @see org.mozilla.javascript.Script
+ */
+ public final Script compileString(
+ String source, String sourceName, int lineno, Object securityDomain) {
+ return null;
+ }
+
+ /**
+ * Compile a JavaScript function.
+ *
+ *
The function source must be a function definition as defined by ECMA (e.g., "function f(a)
+ * { return a; }").
+ *
+ * @param scope the scope to compile relative to
+ * @param source the function definition source
+ * @param sourceName a string describing the source, such as a filename
+ * @param lineno the starting line number
+ * @param securityDomain an arbitrary object that specifies security information about the
+ * origin or owner of the script. For implementations that don't care about security, this
+ * value may be null.
+ * @return a Function that may later be called
+ * @see org.mozilla.javascript.Function
+ */
+ public final Function compileFunction(
+ Scriptable scope, String source, String sourceName, int lineno, Object securityDomain) {
+ return null;
+ }
+
/**
* Convert the value to a JavaScript boolean value.
*
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/DefiningClassLoader.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/DefiningClassLoader.java
new file mode 100644
index 00000000000..3819798c351
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/DefiningClassLoader.java
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ package org.mozilla.javascript;
+
+ /**
+ * Load generated classes.
+ *
+ * @author Norris Boyd
+ */
+ public class DefiningClassLoader extends ClassLoader
+ implements GeneratedClassLoader
+ {
+ public DefiningClassLoader() {
+ }
+
+ public DefiningClassLoader(ClassLoader parentLoader) {
+ }
+
+ @Override
+ public Class> defineClass(String name, byte[] data) {
+ return null;
+ }
+
+ @Override
+ public void linkClass(Class> cl) {
+ }
+
+ @Override
+ public Class> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ return null;
+ }
+ }
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Function.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Function.java
new file mode 100644
index 00000000000..a35a7c2dfba
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Function.java
@@ -0,0 +1,46 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * This is interface that all functions in JavaScript must implement. The interface provides for
+ * calling functions and constructors.
+ *
+ * @see org.mozilla.javascript.Scriptable
+ * @author Norris Boyd
+ */
+public interface Function extends Scriptable {
+ /**
+ * Call the function.
+ *
+ *
Note that the array of arguments is not guaranteed to have length greater than 0.
+ *
+ * @param cx the current Context for this thread
+ * @param scope the scope to execute the function relative to. This is set to the value returned
+ * by getParentScope() except when the function is called from a closure.
+ * @param thisObj the JavaScript this object
+ * @param args the array of arguments
+ * @return the result of the call
+ */
+ Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args);
+
+ /**
+ * Call the function as a constructor.
+ *
+ *
This method is invoked by the runtime in order to satisfy a use of the JavaScript
+ * new operator. This method is expected to create a new object and return it.
+ *
+ * @param cx the current Context for this thread
+ * @param scope an enclosing scope of the caller except when the function is called from a
+ * closure.
+ * @param args the array of arguments
+ * @return the allocated object
+ */
+ Scriptable construct(Context cx, Scriptable scope, Object[] args);
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/GeneratedClassLoader.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/GeneratedClassLoader.java
new file mode 100644
index 00000000000..c7450862917
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/GeneratedClassLoader.java
@@ -0,0 +1,34 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * Interface to define classes from generated byte code.
+ */
+public interface GeneratedClassLoader {
+
+ /**
+ * Define a new Java class.
+ * Classes created via this method should have the same class loader.
+ *
+ * @param name fully qualified class name
+ * @param data class byte code
+ * @return new class object
+ */
+ public Class> defineClass(String name, byte[] data);
+
+ /**
+ * Link the given class.
+ *
+ * @param cl Class instance returned from the previous call to
+ * {@link #defineClass(String, byte[])}
+ * @see java.lang.ClassLoader
+ */
+ public void linkClass(Class> cl);
+}
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Script.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Script.java
new file mode 100644
index 00000000000..824dc0241c1
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/Script.java
@@ -0,0 +1,41 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// API class
+
+package org.mozilla.javascript;
+
+/**
+ * All compiled scripts implement this interface.
+ *
+ * This class encapsulates script execution relative to an
+ * object scope.
+ * @since 1.3
+ * @author Norris Boyd
+ */
+
+public interface Script {
+
+ /**
+ * Execute the script.
+ *
+ * The script is executed in a particular runtime Context, which
+ * must be associated with the current thread.
+ * The script is executed relative to a scope--definitions and
+ * uses of global top-level variables and functions will access
+ * properties of the scope object. For compliant ECMA
+ * programs, the scope must be an object that has been initialized
+ * as a global object using Context.initStandardObjects.
+ *
+ *
+ * @param cx the Context associated with the current thread
+ * @param scope the scope to execute relative to
+ * @return the result of executing the script
+ * @see org.mozilla.javascript.Context#initStandardObjects()
+ */
+ public Object exec(Context cx, Scriptable scope);
+
+}
\ No newline at end of file
diff --git a/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/optimizer/ClassCompiler.java b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/optimizer/ClassCompiler.java
new file mode 100644
index 00000000000..cb2332d3f61
--- /dev/null
+++ b/java/ql/test/experimental/stubs/rhino-1.7.13/org/mozilla/javascript/optimizer/ClassCompiler.java
@@ -0,0 +1,112 @@
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ package org.mozilla.javascript.optimizer;
+
+ import org.mozilla.javascript.CompilerEnvirons;
+
+ /**
+ * Generates class files from script sources.
+ *
+ * since 1.5 Release 5
+ * @author Igor Bukanov
+ */
+
+ public class ClassCompiler
+ {
+ /**
+ * Construct ClassCompiler that uses the specified compiler environment
+ * when generating classes.
+ */
+ public ClassCompiler(CompilerEnvirons compilerEnv)
+ {
+ }
+
+ /**
+ * Set the class name to use for main method implementation.
+ * The class must have a method matching
+ * public static void main(Script sc, String[] args), it will be
+ * called when main(String[] args) is called in the generated
+ * class. The class name should be fully qulified name and include the
+ * package name like in org.foo.Bar.
+ */
+ public void setMainMethodClass(String className)
+ {
+ }
+
+ /**
+ * Get the name of the class for main method implementation.
+ * @see #setMainMethodClass(String)
+ */
+ public String getMainMethodClass()
+ {
+ return null;
+ }
+
+ /**
+ * Get the compiler environment the compiler uses.
+ */
+ public CompilerEnvirons getCompilerEnv()
+ {
+ return null;
+ }
+
+ /**
+ * Get the class that the generated target will extend.
+ */
+ public Class> getTargetExtends()
+ {
+ return null;
+ }
+
+ /**
+ * Set the class that the generated target will extend.
+ *
+ * @param extendsClass the class it extends
+ */
+ public void setTargetExtends(Class> extendsClass)
+ {
+ }
+
+ /**
+ * Get the interfaces that the generated target will implement.
+ */
+ public Class>[] getTargetImplements()
+ {
+ return null;
+ }
+
+ /**
+ * Set the interfaces that the generated target will implement.
+ *
+ * @param implementsClasses an array of Class objects, one for each
+ * interface the target will extend
+ */
+ public void setTargetImplements(Class>[] implementsClasses)
+ {
+ }
+
+ /**
+ * Compile JavaScript source into one or more Java class files.
+ * The first compiled class will have name mainClassName.
+ * If the results of {@link #getTargetExtends()} or
+ * {@link #getTargetImplements()} are not null, then the first compiled
+ * class will extend the specified super class and implement
+ * specified interfaces.
+ *
+ * @return array where elements with even indexes specifies class name
+ * and the following odd index gives class file body as byte[]
+ * array. The initial element of the array always holds
+ * mainClassName and array[1] holds its byte code.
+ */
+ public Object[] compileToClassFiles(String source,
+ String sourceLocation,
+ int lineno,
+ String mainClassName)
+ {
+ return null;
+ }
+ }
\ No newline at end of file
diff --git a/java/ql/test/stubs/scriptengine/javax/script/Bindings.java b/java/ql/test/stubs/scriptengine/javax/script/Bindings.java
new file mode 100644
index 00000000000..a8eeeb6fe5e
--- /dev/null
+++ b/java/ql/test/stubs/scriptengine/javax/script/Bindings.java
@@ -0,0 +1,14 @@
+package javax.script;
+import java.util.Map;
+
+public interface Bindings extends Map {
+ public Object put(String name, Object value);
+
+ public void putAll(Map extends String, ? extends Object> toMerge);
+
+ public boolean containsKey(Object key);
+
+ public Object get(Object key);
+
+ public Object remove(Object key);
+}
diff --git a/java/ql/test/stubs/scriptengine/javax/script/Compilable.java b/java/ql/test/stubs/scriptengine/javax/script/Compilable.java
new file mode 100644
index 00000000000..ce6700c5a66
--- /dev/null
+++ b/java/ql/test/stubs/scriptengine/javax/script/Compilable.java
@@ -0,0 +1,9 @@
+package javax.script;
+
+import java.io.Reader;
+
+public interface Compilable {
+ public CompiledScript compile(String script) throws ScriptException;
+
+ public CompiledScript compile(Reader script) throws ScriptException;
+}
diff --git a/java/ql/test/stubs/scriptengine/javax/script/CompiledScript.java b/java/ql/test/stubs/scriptengine/javax/script/CompiledScript.java
new file mode 100644
index 00000000000..2f03d58c9a7
--- /dev/null
+++ b/java/ql/test/stubs/scriptengine/javax/script/CompiledScript.java
@@ -0,0 +1,17 @@
+package javax.script;
+
+public abstract class CompiledScript {
+
+ public abstract Object eval(ScriptContext context) throws ScriptException;
+
+ public Object eval(Bindings bindings) throws ScriptException {
+ return null;
+ }
+
+ public Object eval() throws ScriptException {
+ return null;
+ }
+
+ public abstract ScriptEngine getEngine();
+
+}
\ No newline at end of file
diff --git a/java/ql/test/stubs/scriptengine/javax/script/ScriptEngine.java b/java/ql/test/stubs/scriptengine/javax/script/ScriptEngine.java
index 4dc4f8c3186..35b91119e4f 100644
--- a/java/ql/test/stubs/scriptengine/javax/script/ScriptEngine.java
+++ b/java/ql/test/stubs/scriptengine/javax/script/ScriptEngine.java
@@ -2,5 +2,7 @@ package javax.script;
public interface ScriptEngine {
Object eval(String var1) throws ScriptException;
+
+ public ScriptEngineFactory getFactory();
}
diff --git a/java/ql/test/stubs/scriptengine/javax/script/ScriptEngineFactory.java b/java/ql/test/stubs/scriptengine/javax/script/ScriptEngineFactory.java
index 7441c8a4ade..f802d86f80b 100644
--- a/java/ql/test/stubs/scriptengine/javax/script/ScriptEngineFactory.java
+++ b/java/ql/test/stubs/scriptengine/javax/script/ScriptEngineFactory.java
@@ -1,6 +1,11 @@
package javax.script;
public interface ScriptEngineFactory {
+ public String getEngineName();
+
+ public String getMethodCallSyntax(String obj, String m, String... args);
+
+ public String getProgram(String... statements);
+
ScriptEngine getScriptEngine();
}
-
diff --git a/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/ClassFilter.java b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/ClassFilter.java
new file mode 100644
index 00000000000..fcc624fc106
--- /dev/null
+++ b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/ClassFilter.java
@@ -0,0 +1,5 @@
+package jdk.nashorn.api.scripting;
+
+public interface ClassFilter {
+ public boolean exposeToScripts(String className);
+}
diff --git a/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngine.java b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 8dc3c1afa10..e89282dfa27 100644
--- a/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -1,10 +1,31 @@
package jdk.nashorn.api.scripting;
-import javax.script.*;
+import java.io.Reader;
-public final class NashornScriptEngine extends AbstractScriptEngine {
+import javax.script.AbstractScriptEngine;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable {
public Object eval(String var1) throws ScriptException {
return null;
}
-}
+ @Override
+ public ScriptEngineFactory getFactory() {
+ return null;
+ }
+
+ @Override
+ public CompiledScript compile(final Reader reader) throws ScriptException {
+ return null;
+ }
+
+ @Override
+ public CompiledScript compile(final String str) throws ScriptException {
+ return null;
+ }
+}
diff --git a/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
index 763e098ddbe..177bf463eb3 100644
--- a/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
+++ b/java/ql/test/stubs/scriptengine/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
@@ -3,20 +3,48 @@ package jdk.nashorn.api.scripting;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
-
public final class NashornScriptEngineFactory implements ScriptEngineFactory {
public NashornScriptEngineFactory() {
}
+ @Override
+ public String getEngineName() {
+ return null;
+ }
+ @Override
+ public String getMethodCallSyntax(final String obj, final String method, final String... args) {
+ return null;
+ }
+
+ @Override
+ public String getProgram(final String... statements) {
+ return null;
+ }
+
+ @Override
public ScriptEngine getScriptEngine() {
return null;
}
+ public ScriptEngine getScriptEngine(final ClassLoader appLoader) {
+ return null;
+ }
- public ScriptEngine getScriptEngine(String... args) {
+ public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
+ return null;
+ }
+
+ public ScriptEngine getScriptEngine(final String... args) {
+ return null;
+ }
+
+ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
+ return null;
+ }
+
+ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
return null;
}
}
-
From e4699f7fa9a142158c1207ccbc8ac31d667ed782 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 11 May 2021 20:09:37 +0000
Subject: [PATCH 162/168] Optimize the query
---
.../Security/CWE/CWE-094/RhinoInjection.java | 9 +-
.../Security/CWE/CWE-094/ScriptInjection.ql | 33 +++---
.../security/CWE-094/RhinoServlet.java | 5 +-
.../security/CWE-094/ScriptEngineTest.java | 42 +++++---
.../security/CWE-094/ScriptInjection.expected | 102 +++++++++---------
5 files changed, 99 insertions(+), 92 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
index 4a87d5bc354..15adfbe4524 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/RhinoInjection.java
@@ -1,3 +1,7 @@
+import org.mozilla.javascript.ClassShutter;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+
public class RhinoInjection extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
@@ -20,10 +24,7 @@ public class RhinoInjection extends HttpServlet {
Scriptable scope = ctx.initStandardObjects();
ctx.setClassShutter(new ClassShutter() {
public boolean visibleToScripts(String className) {
- if(className.startsWith("com.example.")) {
- return true;
- }
- return false;
+ return className.startsWith("com.example.");
}
});
}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index d4f8cfa5370..0819f85c17e 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -1,7 +1,7 @@
/**
* @name Injection in Java Script Engine
- * @description Evaluation of a user-controlled malicious JavaScript or Java expression in
- * Java Script Engine may lead to remote code execution.
+ * @description Evaluation of user-controlled data using the Java Script Engine may
+ * lead to remote code execution.
* @kind path-problem
* @problem.severity error
* @precision high
@@ -78,43 +78,37 @@ predicate scriptEngine(MethodAccess ma, Expr sink) {
}
/**
- * Holds if a Rhino expression evaluation method has the code injection vulnerability.
+ * Holds if a Rhino expression evaluation method is vulnerable to code injection.
*/
predicate evaluateRhinoExpression(MethodAccess ma, Expr sink) {
exists(RhinoEvaluateExpressionMethod m | m = ma.getMethod() |
(
- sink = ma.getArgument(1) and // The second argument is the JavaScript or Java input
- not ma.getMethod().getName() = "compileReader"
- or
- sink = ma.getArgument(0) and // The first argument is the input reader
- ma.getMethod().getName() = "compileReader"
+ if ma.getMethod().getName() = "compileReader"
+ then sink = ma.getArgument(0) // The first argument is the input reader
+ else sink = ma.getArgument(1) // The second argument is the JavaScript or Java input
) and
not exists(MethodAccess ca |
- (
- ca.getMethod().hasName("initSafeStandardObjects") // safe mode
- or
- ca.getMethod().hasName("setClassShutter") // `ClassShutter` constraint is enforced
- ) and
+ ca.getMethod().hasName(["initSafeStandardObjects", "setClassShutter"]) and // safe mode or `ClassShutter` constraint is enforced
ma.getQualifier() = ca.getQualifier().(VarAccess).getVariable().getAnAccess()
)
)
}
/**
- * Holds if a Rhino expression compilation method has the code injection vulnerability.
+ * Holds if a Rhino expression compilation method is vulnerable to code injection.
*/
predicate compileScript(MethodAccess ma, Expr sink) {
exists(RhinoCompileClassMethod m | m = ma.getMethod() | sink = ma.getArgument(0))
}
/**
- * Holds if a Rhino class loading method has the code injection vulnerability.
+ * Holds if a Rhino class loading method is vulnerable to code injection.
*/
predicate defineClass(MethodAccess ma, Expr sink) {
exists(RhinoDefineClassMethod m | m = ma.getMethod() | sink = ma.getArgument(1))
}
-/** A sink of script injection. */
+/** A script injection sink. */
class ScriptInjectionSink extends DataFlow::ExprNode {
ScriptInjectionSink() {
scriptEngine(_, this.getExpr()) or
@@ -123,6 +117,7 @@ class ScriptInjectionSink extends DataFlow::ExprNode {
defineClass(_, this.getExpr())
}
+ /** An access to the method associated with this sink. */
MethodAccess getMethodAccess() {
scriptEngine(result, this.getExpr()) or
evaluateRhinoExpression(result, this.getExpr()) or
@@ -134,11 +129,7 @@ class ScriptInjectionSink extends DataFlow::ExprNode {
class ScriptInjectionConfiguration extends TaintTracking::Configuration {
ScriptInjectionConfiguration() { this = "ScriptInjectionConfiguration" }
- override predicate isSource(DataFlow::Node source) {
- source instanceof RemoteFlowSource
- or
- source instanceof LocalUserInput
- }
+ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ScriptInjectionSink }
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
index 2c863b6f62f..e76a9543f87 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/RhinoServlet.java
@@ -63,10 +63,7 @@ public class RhinoServlet extends HttpServlet {
Scriptable scope = ctx.initStandardObjects();
ctx.setClassShutter(new ClassShutter() {
public boolean visibleToScripts(String className) {
- if(className.startsWith("com.example.")) {
- return true;
- }
- return false;
+ return className.startsWith("com.example.");
}
});
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java b/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java
index 42d9cad6e64..ed7099d7598 100755
--- a/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java
@@ -1,9 +1,21 @@
+import javax.script.AbstractScriptEngine;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
-import javax.script.*;
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
-public class ScriptEngineTest {
+public class ScriptEngineTest extends HttpServlet {
public void testWithScriptEngineReference(String input) throws ScriptException {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
@@ -47,16 +59,7 @@ public class ScriptEngineTest {
String program = engine.getFactory().getProgram(input);
Object result = engine.eval(program);
}
-
- public static void main(String[] args) throws ScriptException {
- new ScriptEngineTest().testWithScriptEngineReference(args[0]);
- new ScriptEngineTest().testNashornWithScriptEngineReference(args[0]);
- new ScriptEngineTest().testNashornWithNashornScriptEngineReference(args[0]);
- new ScriptEngineTest().testCustomScriptEngineReference(args[0]);
- new ScriptEngineTest().testScriptEngineCompilable(args[0]);
- new ScriptEngineTest().testScriptEngineGetProgram(args[0]);
- }
-
+
private static class MyCustomScriptEngine extends AbstractScriptEngine {
public Object eval(String var1) throws ScriptException { return null; }
@@ -82,4 +85,19 @@ public class ScriptEngineTest {
@Override
public String getProgram(final String... statements) { return null; }
}
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ try {
+ String code = request.getParameter("code");
+
+ new ScriptEngineTest().testWithScriptEngineReference(code);
+ new ScriptEngineTest().testNashornWithScriptEngineReference(code);
+ new ScriptEngineTest().testNashornWithNashornScriptEngineReference(code);
+ new ScriptEngineTest().testCustomScriptEngineReference(code);
+ new ScriptEngineTest().testScriptEngineCompilable(code);
+ new ScriptEngineTest().testScriptEngineGetProgram(code);
+ } catch (ScriptException se) {
+ throw new IOException(se.getMessage());
+ }
+ }
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/ScriptInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-094/ScriptInjection.expected
index 0c191a4f579..5f1d250e9a2 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-094/ScriptInjection.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-094/ScriptInjection.expected
@@ -1,58 +1,58 @@
edges
| RhinoServlet.java:28:23:28:50 | getParameter(...) : String | RhinoServlet.java:32:55:32:58 | code |
-| RhinoServlet.java:84:23:84:50 | getParameter(...) : String | RhinoServlet.java:86:54:86:57 | code |
-| RhinoServlet.java:91:23:91:50 | getParameter(...) : String | RhinoServlet.java:92:74:92:88 | getBytes(...) |
-| ScriptEngineTest.java:8:44:8:55 | input : String | ScriptEngineTest.java:12:37:12:41 | input |
-| ScriptEngineTest.java:15:51:15:62 | input : String | ScriptEngineTest.java:19:31:19:35 | input |
-| ScriptEngineTest.java:23:58:23:69 | input : String | ScriptEngineTest.java:27:31:27:35 | input |
-| ScriptEngineTest.java:30:46:30:57 | input : String | ScriptEngineTest.java:34:31:34:35 | input |
-| ScriptEngineTest.java:37:41:37:52 | input : String | ScriptEngineTest.java:40:42:40:46 | input |
-| ScriptEngineTest.java:44:41:44:52 | input : String | ScriptEngineTest.java:47:51:47:55 | input |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:52:56:52:62 | ...[...] : String |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:53:63:53:69 | ...[...] : String |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:54:70:54:76 | ...[...] : String |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:55:58:55:64 | ...[...] : String |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:56:53:56:59 | ...[...] : String |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:57:53:57:59 | ...[...] : String |
-| ScriptEngineTest.java:52:56:52:62 | ...[...] : String | ScriptEngineTest.java:8:44:8:55 | input : String |
-| ScriptEngineTest.java:53:63:53:69 | ...[...] : String | ScriptEngineTest.java:15:51:15:62 | input : String |
-| ScriptEngineTest.java:54:70:54:76 | ...[...] : String | ScriptEngineTest.java:23:58:23:69 | input : String |
-| ScriptEngineTest.java:55:58:55:64 | ...[...] : String | ScriptEngineTest.java:30:46:30:57 | input : String |
-| ScriptEngineTest.java:56:53:56:59 | ...[...] : String | ScriptEngineTest.java:37:41:37:52 | input : String |
-| ScriptEngineTest.java:57:53:57:59 | ...[...] : String | ScriptEngineTest.java:44:41:44:52 | input : String |
+| RhinoServlet.java:81:23:81:50 | getParameter(...) : String | RhinoServlet.java:83:54:83:57 | code |
+| RhinoServlet.java:88:23:88:50 | getParameter(...) : String | RhinoServlet.java:89:74:89:88 | getBytes(...) |
+| ScriptEngineTest.java:20:44:20:55 | input : String | ScriptEngineTest.java:24:37:24:41 | input |
+| ScriptEngineTest.java:27:51:27:62 | input : String | ScriptEngineTest.java:31:31:31:35 | input |
+| ScriptEngineTest.java:35:58:35:69 | input : String | ScriptEngineTest.java:39:31:39:35 | input |
+| ScriptEngineTest.java:42:46:42:57 | input : String | ScriptEngineTest.java:46:31:46:35 | input |
+| ScriptEngineTest.java:49:41:49:52 | input : String | ScriptEngineTest.java:52:42:52:46 | input |
+| ScriptEngineTest.java:56:41:56:52 | input : String | ScriptEngineTest.java:59:51:59:55 | input |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:93:57:93:60 | code : String |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:94:64:94:67 | code : String |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:95:71:95:74 | code : String |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:96:59:96:62 | code : String |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:97:54:97:57 | code : String |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:98:54:98:57 | code : String |
+| ScriptEngineTest.java:93:57:93:60 | code : String | ScriptEngineTest.java:20:44:20:55 | input : String |
+| ScriptEngineTest.java:94:64:94:67 | code : String | ScriptEngineTest.java:27:51:27:62 | input : String |
+| ScriptEngineTest.java:95:71:95:74 | code : String | ScriptEngineTest.java:35:58:35:69 | input : String |
+| ScriptEngineTest.java:96:59:96:62 | code : String | ScriptEngineTest.java:42:46:42:57 | input : String |
+| ScriptEngineTest.java:97:54:97:57 | code : String | ScriptEngineTest.java:49:41:49:52 | input : String |
+| ScriptEngineTest.java:98:54:98:57 | code : String | ScriptEngineTest.java:56:41:56:52 | input : String |
nodes
| RhinoServlet.java:28:23:28:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| RhinoServlet.java:32:55:32:58 | code | semmle.label | code |
-| RhinoServlet.java:84:23:84:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| RhinoServlet.java:86:54:86:57 | code | semmle.label | code |
-| RhinoServlet.java:91:23:91:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| RhinoServlet.java:92:74:92:88 | getBytes(...) | semmle.label | getBytes(...) |
-| ScriptEngineTest.java:8:44:8:55 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:12:37:12:41 | input | semmle.label | input |
-| ScriptEngineTest.java:15:51:15:62 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:19:31:19:35 | input | semmle.label | input |
-| ScriptEngineTest.java:23:58:23:69 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:27:31:27:35 | input | semmle.label | input |
-| ScriptEngineTest.java:30:46:30:57 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:34:31:34:35 | input | semmle.label | input |
-| ScriptEngineTest.java:37:41:37:52 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:40:42:40:46 | input | semmle.label | input |
-| ScriptEngineTest.java:44:41:44:52 | input : String | semmle.label | input : String |
-| ScriptEngineTest.java:47:51:47:55 | input | semmle.label | input |
-| ScriptEngineTest.java:51:26:51:38 | args : String[] | semmle.label | args : String[] |
-| ScriptEngineTest.java:52:56:52:62 | ...[...] : String | semmle.label | ...[...] : String |
-| ScriptEngineTest.java:53:63:53:69 | ...[...] : String | semmle.label | ...[...] : String |
-| ScriptEngineTest.java:54:70:54:76 | ...[...] : String | semmle.label | ...[...] : String |
-| ScriptEngineTest.java:55:58:55:64 | ...[...] : String | semmle.label | ...[...] : String |
-| ScriptEngineTest.java:56:53:56:59 | ...[...] : String | semmle.label | ...[...] : String |
-| ScriptEngineTest.java:57:53:57:59 | ...[...] : String | semmle.label | ...[...] : String |
+| RhinoServlet.java:81:23:81:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| RhinoServlet.java:83:54:83:57 | code | semmle.label | code |
+| RhinoServlet.java:88:23:88:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| RhinoServlet.java:89:74:89:88 | getBytes(...) | semmle.label | getBytes(...) |
+| ScriptEngineTest.java:20:44:20:55 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:24:37:24:41 | input | semmle.label | input |
+| ScriptEngineTest.java:27:51:27:62 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:31:31:31:35 | input | semmle.label | input |
+| ScriptEngineTest.java:35:58:35:69 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:39:31:39:35 | input | semmle.label | input |
+| ScriptEngineTest.java:42:46:42:57 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:46:31:46:35 | input | semmle.label | input |
+| ScriptEngineTest.java:49:41:49:52 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:52:42:52:46 | input | semmle.label | input |
+| ScriptEngineTest.java:56:41:56:52 | input : String | semmle.label | input : String |
+| ScriptEngineTest.java:59:51:59:55 | input | semmle.label | input |
+| ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| ScriptEngineTest.java:93:57:93:60 | code : String | semmle.label | code : String |
+| ScriptEngineTest.java:94:64:94:67 | code : String | semmle.label | code : String |
+| ScriptEngineTest.java:95:71:95:74 | code : String | semmle.label | code : String |
+| ScriptEngineTest.java:96:59:96:62 | code : String | semmle.label | code : String |
+| ScriptEngineTest.java:97:54:97:57 | code : String | semmle.label | code : String |
+| ScriptEngineTest.java:98:54:98:57 | code : String | semmle.label | code : String |
#select
| RhinoServlet.java:32:29:32:78 | evaluateString(...) | RhinoServlet.java:28:23:28:50 | getParameter(...) : String | RhinoServlet.java:32:55:32:58 | code | Java Script Engine evaluate $@. | RhinoServlet.java:28:23:28:50 | getParameter(...) | user input |
-| RhinoServlet.java:86:25:86:97 | compileToClassFiles(...) | RhinoServlet.java:84:23:84:50 | getParameter(...) : String | RhinoServlet.java:86:54:86:57 | code | Java Script Engine evaluate $@. | RhinoServlet.java:84:23:84:50 | getParameter(...) | user input |
-| RhinoServlet.java:92:23:92:89 | defineClass(...) | RhinoServlet.java:91:23:91:50 | getParameter(...) : String | RhinoServlet.java:92:74:92:88 | getBytes(...) | Java Script Engine evaluate $@. | RhinoServlet.java:91:23:91:50 | getParameter(...) | user input |
-| ScriptEngineTest.java:12:19:12:42 | eval(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:12:37:12:41 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
-| ScriptEngineTest.java:19:19:19:36 | eval(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:19:31:19:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
-| ScriptEngineTest.java:27:19:27:36 | eval(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:27:31:27:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
-| ScriptEngineTest.java:34:19:34:36 | eval(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:34:31:34:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
-| ScriptEngineTest.java:40:27:40:47 | compile(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:40:42:40:46 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
-| ScriptEngineTest.java:47:20:47:56 | getProgram(...) | ScriptEngineTest.java:51:26:51:38 | args : String[] | ScriptEngineTest.java:47:51:47:55 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:51:26:51:38 | args | user input |
+| RhinoServlet.java:83:25:83:97 | compileToClassFiles(...) | RhinoServlet.java:81:23:81:50 | getParameter(...) : String | RhinoServlet.java:83:54:83:57 | code | Java Script Engine evaluate $@. | RhinoServlet.java:81:23:81:50 | getParameter(...) | user input |
+| RhinoServlet.java:89:23:89:89 | defineClass(...) | RhinoServlet.java:88:23:88:50 | getParameter(...) : String | RhinoServlet.java:89:74:89:88 | getBytes(...) | Java Script Engine evaluate $@. | RhinoServlet.java:88:23:88:50 | getParameter(...) | user input |
+| ScriptEngineTest.java:24:19:24:42 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:24:37:24:41 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
+| ScriptEngineTest.java:31:19:31:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:31:31:31:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
+| ScriptEngineTest.java:39:19:39:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:39:31:39:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
+| ScriptEngineTest.java:46:19:46:36 | eval(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:46:31:46:35 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
+| ScriptEngineTest.java:52:27:52:47 | compile(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:52:42:52:46 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
+| ScriptEngineTest.java:59:20:59:56 | getProgram(...) | ScriptEngineTest.java:91:18:91:45 | getParameter(...) : String | ScriptEngineTest.java:59:51:59:55 | input | Java Script Engine evaluate $@. | ScriptEngineTest.java:91:18:91:45 | getParameter(...) | user input |
From 0ac8453398d44181ba9c0334fc8dd3e82ff31298 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 14 May 2021 12:50:24 +0000
Subject: [PATCH 163/168] Allow all arguments of methods in ScriptEngineFactory
---
.../Security/CWE/CWE-094/ScriptInjection.ql | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index 0819f85c17e..9faca9b8630 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -26,6 +26,17 @@ class ScriptEngineMethod extends Method {
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory") and
this.hasName(["getProgram", "getMethodCallSyntax"])
}
+
+ /** Holds if the index is for an injectable parameter. */
+ bindingset[index]
+ predicate isInjectableArgIndex(int index) {
+ if
+ this.getDeclaringType()
+ .getASupertype*()
+ .hasQualifiedName("javax.script", "ScriptEngineFactory")
+ then any()
+ else index = 0
+ }
}
/** The context class `org.mozilla.javascript.Context` of Rhino Java Script Engine. */
@@ -71,9 +82,10 @@ class RhinoDefineClassMethod extends Method {
/** Holds if `ma` is a method access of `ScriptEngineMethod`. */
predicate scriptEngine(MethodAccess ma, Expr sink) {
- exists(Method m | m = ma.getMethod() |
- m instanceof ScriptEngineMethod and
- sink = ma.getArgument(0)
+ exists(ScriptEngineMethod m, int index |
+ m = ma.getMethod() and
+ m.isInjectableArgIndex(index) and
+ sink = ma.getArgument(index)
)
}
From 2c1374bdcf416823fda65365d2296c0961537b31 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 14 May 2021 20:05:56 +0000
Subject: [PATCH 164/168] Use inline implementation for ScriptEngineFactory
---
.../Security/CWE/CWE-094/ScriptInjection.ql | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index 9faca9b8630..5274140158c 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -26,17 +26,6 @@ class ScriptEngineMethod extends Method {
this.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory") and
this.hasName(["getProgram", "getMethodCallSyntax"])
}
-
- /** Holds if the index is for an injectable parameter. */
- bindingset[index]
- predicate isInjectableArgIndex(int index) {
- if
- this.getDeclaringType()
- .getASupertype*()
- .hasQualifiedName("javax.script", "ScriptEngineFactory")
- then any()
- else index = 0
- }
}
/** The context class `org.mozilla.javascript.Context` of Rhino Java Script Engine. */
@@ -82,10 +71,11 @@ class RhinoDefineClassMethod extends Method {
/** Holds if `ma` is a method access of `ScriptEngineMethod`. */
predicate scriptEngine(MethodAccess ma, Expr sink) {
- exists(ScriptEngineMethod m, int index |
+ exists(ScriptEngineMethod m |
m = ma.getMethod() and
- m.isInjectableArgIndex(index) and
- sink = ma.getArgument(index)
+ if m.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory")
+ then sink = ma.getArgument(_) // all arguments allow script injection
+ else sink = ma.getArgument(0)
)
}
From 2fa249a8eba1314acca9e7a953f5c3ed658c5b39 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 14 May 2021 20:31:05 +0000
Subject: [PATCH 165/168] Update method name and qldoc
---
.../Security/CWE/CWE-094/ScriptInjection.ql | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index 5274140158c..71accb28c37 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -69,8 +69,11 @@ class RhinoDefineClassMethod extends Method {
}
}
-/** Holds if `ma` is a method access of `ScriptEngineMethod`. */
-predicate scriptEngine(MethodAccess ma, Expr sink) {
+/**
+ * Holds if `ma` is a call to a `ScriptEngineMethod` and `sink` is an argument that
+ * will be executed.
+ */
+predicate isScriptArgument(MethodAccess ma, Expr sink) {
exists(ScriptEngineMethod m |
m = ma.getMethod() and
if m.getDeclaringType().getASupertype*().hasQualifiedName("javax.script", "ScriptEngineFactory")
@@ -113,7 +116,7 @@ predicate defineClass(MethodAccess ma, Expr sink) {
/** A script injection sink. */
class ScriptInjectionSink extends DataFlow::ExprNode {
ScriptInjectionSink() {
- scriptEngine(_, this.getExpr()) or
+ isScriptArgument(_, this.getExpr()) or
evaluateRhinoExpression(_, this.getExpr()) or
compileScript(_, this.getExpr()) or
defineClass(_, this.getExpr())
@@ -121,7 +124,7 @@ class ScriptInjectionSink extends DataFlow::ExprNode {
/** An access to the method associated with this sink. */
MethodAccess getMethodAccess() {
- scriptEngine(result, this.getExpr()) or
+ isScriptArgument(result, this.getExpr()) or
evaluateRhinoExpression(result, this.getExpr()) or
compileScript(result, this.getExpr()) or
defineClass(result, this.getExpr())
From 9d392263a51e77783b78022839aa52ab37c7ba64 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Mon, 17 May 2021 16:07:00 +0000
Subject: [PATCH 166/168] Refactor inconsistent method names
---
.../Security/CWE/CWE-094/ScriptInjection.ql | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index 71accb28c37..aa5a8b74f93 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -85,7 +85,7 @@ predicate isScriptArgument(MethodAccess ma, Expr sink) {
/**
* Holds if a Rhino expression evaluation method is vulnerable to code injection.
*/
-predicate evaluateRhinoExpression(MethodAccess ma, Expr sink) {
+predicate evaluatesRhinoExpression(MethodAccess ma, Expr sink) {
exists(RhinoEvaluateExpressionMethod m | m = ma.getMethod() |
(
if ma.getMethod().getName() = "compileReader"
@@ -102,14 +102,14 @@ predicate evaluateRhinoExpression(MethodAccess ma, Expr sink) {
/**
* Holds if a Rhino expression compilation method is vulnerable to code injection.
*/
-predicate compileScript(MethodAccess ma, Expr sink) {
+predicate compilesScript(MethodAccess ma, Expr sink) {
exists(RhinoCompileClassMethod m | m = ma.getMethod() | sink = ma.getArgument(0))
}
/**
* Holds if a Rhino class loading method is vulnerable to code injection.
*/
-predicate defineClass(MethodAccess ma, Expr sink) {
+predicate definesRhinoClass(MethodAccess ma, Expr sink) {
exists(RhinoDefineClassMethod m | m = ma.getMethod() | sink = ma.getArgument(1))
}
@@ -117,17 +117,17 @@ predicate defineClass(MethodAccess ma, Expr sink) {
class ScriptInjectionSink extends DataFlow::ExprNode {
ScriptInjectionSink() {
isScriptArgument(_, this.getExpr()) or
- evaluateRhinoExpression(_, this.getExpr()) or
- compileScript(_, this.getExpr()) or
- defineClass(_, this.getExpr())
+ evaluatesRhinoExpression(_, this.getExpr()) or
+ compilesScript(_, this.getExpr()) or
+ definesRhinoClass(_, this.getExpr())
}
/** An access to the method associated with this sink. */
MethodAccess getMethodAccess() {
isScriptArgument(result, this.getExpr()) or
- evaluateRhinoExpression(result, this.getExpr()) or
- compileScript(result, this.getExpr()) or
- defineClass(result, this.getExpr())
+ evaluatesRhinoExpression(result, this.getExpr()) or
+ compilesScript(result, this.getExpr()) or
+ definesRhinoClass(result, this.getExpr())
}
}
From d4323a4a540372b0d3a38ebe8a8e53d2af3de462 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Mon, 17 May 2021 20:15:09 +0000
Subject: [PATCH 167/168] Update qldoc
---
.../experimental/Security/CWE/CWE-094/ScriptInjection.qhelp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.qhelp
index 586304ebb7c..2683cf9ad29 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.qhelp
@@ -4,7 +4,7 @@
-
The Java Scripting API has been available since the release of Java 6, which allows
+
The Java Scripting API has been available since the release of Java 6. It allows
applications to interact with scripts written in languages such as JavaScript. It serves
as an embedded scripting engine inside Java applications which allows Java-to-JavaScript
interoperability and provides a seamless integration between the two languages. If an
@@ -21,7 +21,7 @@
-
The following code could execute random JavaScript code in ScriptEngine
+
The following code could execute user-supplied JavaScript code in ScriptEngine
From 02aa9c6fc7bde93ab56a1dc78423499d023978fe Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 18 May 2021 12:09:52 +0000
Subject: [PATCH 168/168] Optimize the sink and update qldoc
---
.../Security/CWE/CWE-094/ScriptInjection.ql | 21 ++++++++++---------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
index aa5a8b74f93..fb8bf867501 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-094/ScriptInjection.ql
@@ -115,22 +115,23 @@ predicate definesRhinoClass(MethodAccess ma, Expr sink) {
/** A script injection sink. */
class ScriptInjectionSink extends DataFlow::ExprNode {
+ MethodAccess methodAccess;
+
ScriptInjectionSink() {
- isScriptArgument(_, this.getExpr()) or
- evaluatesRhinoExpression(_, this.getExpr()) or
- compilesScript(_, this.getExpr()) or
- definesRhinoClass(_, this.getExpr())
+ isScriptArgument(methodAccess, this.getExpr()) or
+ evaluatesRhinoExpression(methodAccess, this.getExpr()) or
+ compilesScript(methodAccess, this.getExpr()) or
+ definesRhinoClass(methodAccess, this.getExpr())
}
/** An access to the method associated with this sink. */
- MethodAccess getMethodAccess() {
- isScriptArgument(result, this.getExpr()) or
- evaluatesRhinoExpression(result, this.getExpr()) or
- compilesScript(result, this.getExpr()) or
- definesRhinoClass(result, this.getExpr())
- }
+ MethodAccess getMethodAccess() { result = methodAccess }
}
+/**
+ * A taint tracking configuration that tracks flow from `RemoteFlowSource` to an argument
+ * of a method call that executes injected script.
+ */
class ScriptInjectionConfiguration extends TaintTracking::Configuration {
ScriptInjectionConfiguration() { this = "ScriptInjectionConfiguration" }