From 07f45a51f8230c920acdfb231255967fc29d9b7c Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Wed, 13 Jan 2021 02:49:00 +0000
Subject: [PATCH 001/296] Query to detect hash without salt
---
.../CWE-759/HashWithoutSalt.cs | 74 ++++++++++++++
.../CWE-759/HashWithoutSalt.expected | 13 +++
.../CWE-759/HashWithoutSalt.qhelp | 29 ++++++
.../CWE-759/HashWithoutSalt.ql | 98 +++++++++++++++++++
.../Security Features/CWE-759/Stubs.cs | 45 +++++++++
5 files changed, 259 insertions(+)
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.qhelp
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
new file mode 100644
index 00000000000..3356c0f1773
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
@@ -0,0 +1,74 @@
+// semmle-extractor-options: /r:System.Security.Cryptography.Primitives.dll /r:System.Security.Cryptography.Csp.dll /r:System.Security.Cryptography.Algorithms.dll
+
+using System;
+using System.Security.Cryptography;
+
+using Windows.Security.Cryptography;
+using Windows.Security.Cryptography.Core;
+using Windows.Storage.Streams;
+
+public class Test
+{
+ private const int SaltSize = 32;
+
+ // BAD - Hash without a salt.
+ public static String HashPassword(string password, string strAlgName ="SHA256")
+ {
+ IBuffer passBuff = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
+ HashAlgorithmProvider algProvider = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
+ IBuffer hashBuff = algProvider.HashData(passBuff);
+ return CryptographicBuffer.EncodeToBase64String(hashBuff);
+ }
+
+ // GOOD - Hash with a salt.
+ public static string HashPassword2(string password, string salt, string strAlgName ="SHA256")
+ {
+ // Concatenate the salt with the password.
+ IBuffer passBuff = CryptographicBuffer.ConvertStringToBinary(password+salt, BinaryStringEncoding.Utf8);
+ HashAlgorithmProvider algProvider = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
+ IBuffer hashBuff = algProvider.HashData(passBuff);
+ return CryptographicBuffer.EncodeToBase64String(hashBuff);
+ }
+
+ // BAD - Hash without a salt.
+ public static string HashPassword(string password)
+ {
+ SHA256 sha256Hash = SHA256.Create();
+ byte[] passBytes = System.Text.Encoding.ASCII.GetBytes(password);
+ byte[] hashBytes = sha256Hash.ComputeHash(passBytes);
+ return Convert.ToBase64String(hashBytes);
+ }
+
+ // GOOD - Hash with a salt.
+ public static string HashPassword2(string password)
+ {
+ byte[] passBytes = System.Text.Encoding.ASCII.GetBytes(password);
+ byte[] saltBytes = GenerateSalt();
+
+ // Add the salt to the hash.
+ byte[] rawSalted = new byte[passBytes.Length + saltBytes.Length];
+ passBytes.CopyTo(rawSalted, 0);
+ saltBytes.CopyTo(rawSalted, passBytes.Length);
+
+ //Create the salted hash.
+ SHA256 sha256 = SHA256.Create();
+ byte[] saltedPassBytes = sha256.ComputeHash(rawSalted);
+
+ // Add the salt value to the salted hash.
+ byte[] dbPassword = new byte[saltedPassBytes.Length + saltBytes.Length];
+ saltedPassBytes.CopyTo(dbPassword, 0);
+ saltBytes.CopyTo(dbPassword, saltedPassBytes.Length);
+
+ return Convert.ToBase64String(dbPassword);
+ }
+
+ public static byte[] GenerateSalt()
+ {
+ using (var rng = new RNGCryptoServiceProvider())
+ {
+ var randomNumber = new byte[SaltSize];
+ rng.GetBytes(randomNumber);
+ return randomNumber;
+ }
+ }
+}
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected
new file mode 100644
index 00000000000..8a89533f13e
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected
@@ -0,0 +1,13 @@
+edges
+| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff |
+| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes |
+| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] |
+nodes
+| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | semmle.label | access to local variable passBuff |
+| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | semmle.label | access to local variable passBytes |
+#select
+| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:17:70:17:77 | access to parameter password | The password |
+| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:37:64:37:71 | access to parameter password | The password |
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.qhelp b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.qhelp
new file mode 100644
index 00000000000..3e0583f92ea
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.qhelp
@@ -0,0 +1,29 @@
+
+
+
+
+ In cryptography, a salt is some random data used as an additional input to a one-way function that hashes a password or pass-phrase. It makes dictionary attacks more difficult.
+
+ Without a salt, it is much easier for attackers to pre-compute the hash value using dictionary attack techniques such as rainbow tables to crack passwords.
+
+
+
+ Use a long random salt of at least 32 bytes then use the combination of password and salt to hash a password or password phrase.
+
+
+
+ The following example shows two ways of hashing. In the 'BAD' cases, no salt is provided. In the 'GOOD' cases, a salt is provided.
+
+
+
+
+
+ DZone:
+ A Look at Java Cryptography
+
+
+ CWE:
+ CWE-759: Use of a One-Way Hash without a Salt
+
+
+
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
new file mode 100644
index 00000000000..387a5cb3751
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -0,0 +1,98 @@
+/**
+ * @name Use of a hash function without a salt
+ * @description Hashed passwords without a salt are vulnerable to dictionary attacks.
+ * @kind path-problem
+ * @id cs/hash-without-salt
+ * @tags security
+ * external/cwe-759
+ */
+
+import csharp
+import semmle.code.csharp.dataflow.TaintTracking
+import DataFlow::PathGraph
+
+/** The C# class `System.Security.Cryptography.SHA...` other than the weak `SHA1`. */
+class SHA extends RefType {
+ SHA() { this.getQualifiedName().regexpMatch("System\\.Security\\.Cryptography\\.SHA\\d{2,3}") }
+}
+
+class HashAlgorithmProvider extends RefType {
+ HashAlgorithmProvider() {
+ this.hasQualifiedName("Windows.Security.Cryptography.Core", "HashAlgorithmProvider")
+ }
+}
+
+/** The method call `ComputeHash()` declared in `System.Security.Cryptography.SHA...`. */
+class ComputeHashMethodCall extends MethodCall {
+ ComputeHashMethodCall() {
+ this.getQualifier().getType() instanceof SHA and
+ this.getTarget().hasName("ComputeHash")
+ }
+}
+
+/** The method call `ComputeHash()` declared in `System.Security.Cryptography.SHA...`. */
+class HashDataMethodCall extends MethodCall {
+ HashDataMethodCall() {
+ this.getQualifier().getType() instanceof HashAlgorithmProvider and
+ this.getTarget().hasName("HashData")
+ }
+}
+
+/** Gets a regular expression for matching common names of variables that indicate the value being held is a password. */
+string getPasswordRegex() { result = "(?i).*pass(wd|word|code|phrase).*" }
+
+/** Finds variables that hold password information judging by their names. */
+class PasswordVarExpr extends Expr {
+ PasswordVarExpr() {
+ exists(Variable v | this = v.getAnAccess() | v.getName().regexpMatch(getPasswordRegex()))
+ }
+}
+
+/** Taint configuration tracking flow from an expression whose name suggests it holds password data to a method call that generates a hash without a salt. */
+class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
+ HashWithoutSaltConfiguration() { this = "HashWithoutSaltConfiguration" }
+
+ override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof PasswordVarExpr }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(ComputeHashMethodCall mc |
+ sink.asExpr() = mc.getArgument(0) // sha256Hash.ComputeHash(rawDatabytes)
+ ) or
+ exists(HashDataMethodCall mc |
+ sink.asExpr() = mc.getArgument(0) // algProv.HashData(rawDatabytes)
+ )
+ }
+
+ override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
+ exists(MethodCall mc |
+ mc.getTarget()
+ .hasQualifiedName("Windows.Security.Cryptography.CryptographicBuffer",
+ "ConvertStringToBinary") and
+ mc.getArgument(0) = node1.asExpr() and
+ mc = node2.asExpr()
+ )
+ }
+
+ /**
+ * Holds if a password is concatenated with a salt then hashed together through the call `System.Array.CopyTo()`, for example,
+ * `byte[] rawSalted = new byte[passBytes.Length + salt.Length];`
+ * `passBytes.CopyTo(rawSalted, 0);`
+ * `salt.CopyTo(rawSalted, passBytes.Length);`
+ * `byte[] saltedPassword = sha256.ComputeHash(rawSalted);`
+ * Or the password is concatenated with a salt as a string.
+ */
+ override predicate isSanitizer(DataFlow::Node node) {
+ exists(MethodCall mc |
+ mc.getTarget().fromLibrary() and
+ mc.getTarget().hasQualifiedName("System.Array", "CopyTo") and
+ mc.getArgument(0) = node.asExpr()
+ ) // passBytes.CopyTo(rawSalted, 0)
+ or
+ exists(AddExpr e | node.asExpr() = e.getAnOperand()) // password+salt
+ }
+}
+
+from DataFlow::PathNode source, DataFlow::PathNode sink, HashWithoutSaltConfiguration c
+where c.hasFlowPath(source, sink)
+select sink.getNode(), source, sink, "$@ is hashed without a salt.", source.getNode(),
+ "The password"
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs b/csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs
new file mode 100644
index 00000000000..b0401f5c3a5
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs
@@ -0,0 +1,45 @@
+namespace Windows.Security.Cryptography
+{
+ public enum BinaryStringEncoding
+ {
+ Utf8,
+ Utf16LE,
+ Utf16BE
+ }
+
+ public static class CryptographicBuffer
+ {
+ public static Windows.Storage.Streams.IBuffer ConvertStringToBinary(string value, BinaryStringEncoding encoding) => throw null;
+
+ public static string EncodeToBase64String(Windows.Storage.Streams.IBuffer buffer) => throw null;
+ }
+}
+
+namespace Windows.Storage.Streams
+{
+ public interface IBuffer {
+ public uint Capacity { get; }
+
+ public uint Length { get; set; }
+ }
+}
+
+namespace Windows.Security.Cryptography.Core
+{
+ public sealed class CryptographicKey { }
+
+ public sealed class SymmetricKeyAlgorithmProvider
+ {
+ public CryptographicKey CreateSymmetricKey(Windows.Storage.Streams.IBuffer keyMaterial) => throw null;
+ }
+
+ public sealed class HashAlgorithmProvider {
+ public string AlgorithmName { get; }
+
+ public uint HashLength { get; }
+
+ public static HashAlgorithmProvider OpenAlgorithm(string algorithm) => throw null;
+
+ public Windows.Storage.Streams.IBuffer HashData(Windows.Storage.Streams.IBuffer data) => throw null;
+ }
+}
From 46fd5bd92eff7eadfd1ac3a1a7c00fec71569be8 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Wed, 20 Jan 2021 03:51:46 +0000
Subject: [PATCH 002/296] Move test files to the test folder
---
.../CWE-759/HashWithoutSalt.ql | 32 ++++++++-----------
.../CWE-759/HashWithoutSalt.cs | 0
.../CWE-759/HashWithoutSalt.expected | 0
.../CWE-759/HashWithoutSalt.qlref | 1 +
.../Security Features/CWE-759/Stubs.cs | 0
5 files changed, 15 insertions(+), 18 deletions(-)
rename csharp/ql/{src => test}/experimental/Security Features/CWE-759/HashWithoutSalt.cs (100%)
rename csharp/ql/{src => test}/experimental/Security Features/CWE-759/HashWithoutSalt.expected (100%)
create mode 100644 csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.qlref
rename csharp/ql/{src => test}/experimental/Security Features/CWE-759/Stubs.cs (100%)
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
index 387a5cb3751..6f57b5ae03c 100644
--- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -22,19 +22,17 @@ class HashAlgorithmProvider extends RefType {
}
}
-/** The method call `ComputeHash()` declared in `System.Security.Cryptography.SHA...`. */
-class ComputeHashMethodCall extends MethodCall {
- ComputeHashMethodCall() {
- this.getQualifier().getType() instanceof SHA and
- this.getTarget().hasName("ComputeHash")
- }
-}
-
-/** The method call `ComputeHash()` declared in `System.Security.Cryptography.SHA...`. */
-class HashDataMethodCall extends MethodCall {
- HashDataMethodCall() {
- this.getQualifier().getType() instanceof HashAlgorithmProvider and
- this.getTarget().hasName("HashData")
+/**
+ * The method `ComputeHash()` declared in `System.Security.Cryptography.SHA...` and
+ * the method `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
+ */
+class HashMethod extends Method {
+ HashMethod() {
+ this.getDeclaringType() instanceof SHA and
+ this.hasName("ComputeHash")
+ or
+ this.getDeclaringType() instanceof HashAlgorithmProvider and
+ this.hasName("HashData")
}
}
@@ -55,11 +53,9 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof PasswordVarExpr }
override predicate isSink(DataFlow::Node sink) {
- exists(ComputeHashMethodCall mc |
- sink.asExpr() = mc.getArgument(0) // sha256Hash.ComputeHash(rawDatabytes)
- ) or
- exists(HashDataMethodCall mc |
- sink.asExpr() = mc.getArgument(0) // algProv.HashData(rawDatabytes)
+ exists(MethodCall mc |
+ sink.asExpr() = mc.getArgument(0) and
+ mc.getTarget() instanceof HashMethod
)
}
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
similarity index 100%
rename from csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
rename to csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
similarity index 100%
rename from csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.expected
rename to csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.qlref b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.qlref
new file mode 100644
index 00000000000..3739b8998a4
--- /dev/null
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.qlref
@@ -0,0 +1 @@
+experimental/Security Features/CWE-759/HashWithoutSalt.ql
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs b/csharp/ql/test/experimental/Security Features/CWE-759/Stubs.cs
similarity index 100%
rename from csharp/ql/src/experimental/Security Features/CWE-759/Stubs.cs
rename to csharp/ql/test/experimental/Security Features/CWE-759/Stubs.cs
From 8ed2bc59adcc76ed1e65dd7e5c47f6681cc91f3b Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 26 Jan 2021 17:29:52 +0000
Subject: [PATCH 003/296] Add the c# program to src and address the issue with
algorithm type
---
.../CWE-759/HashWithoutSalt.cs | 65 +++++++++++++++++++
.../CWE-759/HashWithoutSalt.ql | 15 +++--
2 files changed, 73 insertions(+), 7 deletions(-)
create mode 100644 csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
new file mode 100644
index 00000000000..309d2e0d785
--- /dev/null
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.cs
@@ -0,0 +1,65 @@
+public class Test
+{
+ private const int SaltSize = 32;
+
+ // BAD - Hash without a salt.
+ public static String HashPassword(string password, string strAlgName ="SHA256")
+ {
+ IBuffer passBuff = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
+ HashAlgorithmProvider algProvider = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
+ IBuffer hashBuff = algProvider.HashData(passBuff);
+ return CryptographicBuffer.EncodeToBase64String(hashBuff);
+ }
+
+ // GOOD - Hash with a salt.
+ public static string HashPassword2(string password, string salt, string strAlgName ="SHA256")
+ {
+ // Concatenate the salt with the password.
+ IBuffer passBuff = CryptographicBuffer.ConvertStringToBinary(password+salt, BinaryStringEncoding.Utf8);
+ HashAlgorithmProvider algProvider = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
+ IBuffer hashBuff = algProvider.HashData(passBuff);
+ return CryptographicBuffer.EncodeToBase64String(hashBuff);
+ }
+
+ // BAD - Hash without a salt.
+ public static string HashPassword(string password)
+ {
+ SHA256 sha256Hash = SHA256.Create();
+ byte[] passBytes = System.Text.Encoding.ASCII.GetBytes(password);
+ byte[] hashBytes = sha256Hash.ComputeHash(passBytes);
+ return Convert.ToBase64String(hashBytes);
+ }
+
+ // GOOD - Hash with a salt.
+ public static string HashPassword2(string password)
+ {
+ byte[] passBytes = System.Text.Encoding.ASCII.GetBytes(password);
+ byte[] saltBytes = GenerateSalt();
+
+ // Add the salt to the hash.
+ byte[] rawSalted = new byte[passBytes.Length + saltBytes.Length];
+ passBytes.CopyTo(rawSalted, 0);
+ saltBytes.CopyTo(rawSalted, passBytes.Length);
+
+ //Create the salted hash.
+ SHA256 sha256 = SHA256.Create();
+ byte[] saltedPassBytes = sha256.ComputeHash(rawSalted);
+
+ // Add the salt value to the salted hash.
+ byte[] dbPassword = new byte[saltedPassBytes.Length + saltBytes.Length];
+ saltedPassBytes.CopyTo(dbPassword, 0);
+ saltBytes.CopyTo(dbPassword, saltedPassBytes.Length);
+
+ return Convert.ToBase64String(dbPassword);
+ }
+
+ public static byte[] GenerateSalt()
+ {
+ using (var rng = new RNGCryptoServiceProvider())
+ {
+ var randomNumber = new byte[SaltSize];
+ rng.GetBytes(randomNumber);
+ return randomNumber;
+ }
+ }
+}
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
index 6f57b5ae03c..07711e5f1f6 100644
--- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -11,24 +11,25 @@ import csharp
import semmle.code.csharp.dataflow.TaintTracking
import DataFlow::PathGraph
-/** The C# class `System.Security.Cryptography.SHA...` other than the weak `SHA1`. */
-class SHA extends RefType {
- SHA() { this.getQualifiedName().regexpMatch("System\\.Security\\.Cryptography\\.SHA\\d{2,3}") }
-}
-
+/** The C# class `Windows.Security.Cryptography.Core.HashAlgorithmProvider`. */
class HashAlgorithmProvider extends RefType {
HashAlgorithmProvider() {
this.hasQualifiedName("Windows.Security.Cryptography.Core", "HashAlgorithmProvider")
}
}
+/** The C# class `System.Security.Cryptography.HashAlgorithm`. */
+class HashAlgorithm extends RefType {
+ HashAlgorithm() { this.hasQualifiedName("System.Security.Cryptography", "HashAlgorithm") }
+}
+
/**
- * The method `ComputeHash()` declared in `System.Security.Cryptography.SHA...` and
+ * The method `ComputeHash()` declared in `System.Security.Cryptography.HashAlgorithm` and
* the method `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
*/
class HashMethod extends Method {
HashMethod() {
- this.getDeclaringType() instanceof SHA and
+ this.getDeclaringType() instanceof HashAlgorithm and
this.hasName("ComputeHash")
or
this.getDeclaringType() instanceof HashAlgorithmProvider and
From f1788ed04e944dca3ecf96226fc9b316f16328dc Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Thu, 11 Feb 2021 04:33:42 +0000
Subject: [PATCH 004/296] Revamp the query to handle more cases
---
.../CWE-759/HashWithoutSalt.ql | 50 +++++++++++++++++--
.../CWE-759/HashWithoutSalt.cs | 50 +++++++++++++++++++
2 files changed, 95 insertions(+), 5 deletions(-)
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
index 07711e5f1f6..94359fa8e07 100644
--- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -8,7 +8,9 @@
*/
import csharp
+import semmle.code.csharp.dataflow.DataFlow2
import semmle.code.csharp.dataflow.TaintTracking
+import semmle.code.csharp.dataflow.TaintTracking2
import DataFlow::PathGraph
/** The C# class `Windows.Security.Cryptography.Core.HashAlgorithmProvider`. */
@@ -23,6 +25,13 @@ class HashAlgorithm extends RefType {
HashAlgorithm() { this.hasQualifiedName("System.Security.Cryptography", "HashAlgorithm") }
}
+/** The C# class `System.Security.Cryptography.KeyedHashAlgorithm`. */
+class KeyedHashAlgorithm extends RefType {
+ KeyedHashAlgorithm() {
+ this.hasQualifiedName("System.Security.Cryptography", "KeyedHashAlgorithm")
+ }
+}
+
/**
* The method `ComputeHash()` declared in `System.Security.Cryptography.HashAlgorithm` and
* the method `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
@@ -47,6 +56,20 @@ class PasswordVarExpr extends Expr {
}
}
+/** Holds if there is another hashing method call. */
+predicate hasAnotherHashCall(MethodCall mc) {
+ exists(Call mc2, DataFlow2::Node src, DataFlow2::Node sink |
+ (
+ mc2.getTarget() instanceof HashMethod or
+ mc2.(ObjectCreation).getObjectType().getABaseType+() instanceof HashAlgorithm
+ ) and
+ mc2 != mc and
+ src.asExpr() = mc.getAReachableElement() and
+ sink.asExpr() = mc2.getAChildExpr() and
+ TaintTracking2::localTaint(src, sink)
+ )
+}
+
/** Taint configuration tracking flow from an expression whose name suggests it holds password data to a method call that generates a hash without a salt. */
class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
HashWithoutSaltConfiguration() { this = "HashWithoutSaltConfiguration" }
@@ -56,7 +79,8 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc |
sink.asExpr() = mc.getArgument(0) and
- mc.getTarget() instanceof HashMethod
+ mc.getTarget() instanceof HashMethod and
+ not hasAnotherHashCall(mc)
)
}
@@ -71,7 +95,7 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
}
/**
- * Holds if a password is concatenated with a salt then hashed together through the call `System.Array.CopyTo()`, for example,
+ * Holds if a password is concatenated with a salt then hashed together through calls such as `System.Array.CopyTo()`, for example,
* `byte[] rawSalted = new byte[passBytes.Length + salt.Length];`
* `passBytes.CopyTo(rawSalted, 0);`
* `salt.CopyTo(rawSalted, passBytes.Length);`
@@ -81,11 +105,27 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) {
exists(MethodCall mc |
mc.getTarget().fromLibrary() and
- mc.getTarget().hasQualifiedName("System.Array", "CopyTo") and
- mc.getArgument(0) = node.asExpr()
- ) // passBytes.CopyTo(rawSalted, 0)
+ (
+ mc.getTarget().hasQualifiedName("System.Array", "CopyTo") or // passBytes.CopyTo(rawSalted, 0)
+ mc.getTarget().hasQualifiedName("System.String", "Concat") or // string.Concat(password, saltkey)
+ mc.getTarget().hasQualifiedName("System.Buffer", "BlockCopy") or // Buffer.BlockCopy(salt, 0, allBytes, 0, 20)
+ mc.getTarget().hasQualifiedName("System.String", "Format") // String.Format("{0}:{1}:{2}", username, salt, password)
+ ) and
+ mc.getAnArgument() = node.asExpr()
+ )
or
exists(AddExpr e | node.asExpr() = e.getAnOperand()) // password+salt
+ or
+ exists(InterpolatedStringExpr e | node.asExpr() = e.getAnInsert())
+ or
+ // a salt or key is included in subclasses of `KeyedHashAlgorithm`
+ exists(MethodCall mc, Assignment ass, ObjectCreation oc |
+ ass.getRValue() = oc and
+ oc.getObjectType().getABaseType+() instanceof KeyedHashAlgorithm and
+ mc.getTarget() instanceof HashMethod and
+ ass.getLValue() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and
+ mc.getArgument(0) = node.asExpr()
+ )
}
}
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
index 3356c0f1773..83cc2607262 100644
--- a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
@@ -62,6 +62,21 @@ public class Test
return Convert.ToBase64String(dbPassword);
}
+ // GOOD - Hash with a salt.
+ public bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
+ {
+ using(var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
+ {
+ var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
+ for(int i = 0;i
Date: Thu, 11 Feb 2021 17:53:42 +0000
Subject: [PATCH 005/296] Add more sinks
---
.../Security Features/CWE-759/HashWithoutSalt.ql | 8 ++++----
.../Security Features/CWE-759/HashWithoutSalt.cs | 9 +++++++++
.../Security Features/CWE-759/HashWithoutSalt.expected | 6 ++++++
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
index 94359fa8e07..5ac93d3004a 100644
--- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -33,15 +33,15 @@ class KeyedHashAlgorithm extends RefType {
}
/**
- * The method `ComputeHash()` declared in `System.Security.Cryptography.HashAlgorithm` and
+ * The method `ComputeHash()`, `ComputeHashAsync`, `TryComputeHash`, `HashData`, or `TryHashData` declared in `System.Security.Cryptography.HashAlgorithm` and
* the method `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
*/
class HashMethod extends Method {
HashMethod() {
- this.getDeclaringType() instanceof HashAlgorithm and
- this.hasName("ComputeHash")
+ this.getDeclaringType().getABaseType*() instanceof HashAlgorithm and
+ this.getName().matches(["%ComputeHash%", "%HashData"])
or
- this.getDeclaringType() instanceof HashAlgorithmProvider and
+ this.getDeclaringType().getABaseType*() instanceof HashAlgorithmProvider and
this.hasName("HashData")
}
}
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
index 83cc2607262..f2278519de0 100644
--- a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
@@ -62,6 +62,15 @@ public class Test
return Convert.ToBase64String(dbPassword);
}
+ // BAD - Hash without a salt.
+ public static string HashPassword3(string password)
+ {
+ HashAlgorithm hashAlg = new SHA256CryptoServiceProvider();
+ byte[] passBytes = System.Text.Encoding.ASCII.GetBytes(password);
+ byte[] hashBytes = hashAlg.ComputeHash(passBytes);
+ return Convert.ToBase64String(hashBytes);
+ }
+
// GOOD - Hash with a salt.
public bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
index 8a89533f13e..752c5912662 100644
--- a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
@@ -2,12 +2,18 @@ edges
| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff |
| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes |
| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes |
+| HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] |
nodes
| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | semmle.label | access to parameter password : String |
| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | semmle.label | access to local variable passBuff |
| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | semmle.label | access to parameter password : String |
| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | semmle.label | access to local variable passBytes |
+| HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | semmle.label | access to local variable passBytes |
#select
| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:17:70:17:77 | access to parameter password | The password |
| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:37:64:37:71 | access to parameter password | The password |
+| HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:69:64:69:71 | access to parameter password | The password |
From 6a2c7d54cdeffc26a20ae86521ec6ac48fd97dda Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Mon, 14 Jun 2021 03:24:16 +0000
Subject: [PATCH 006/296] Enhance the query to check more scenarios
---
.../CWE-759/HashWithoutSalt.ql | 120 ++++++++++++++----
.../CWE-759/HashWithoutSalt.cs | 69 ++++++++++
.../CWE-759/HashWithoutSalt.expected | 32 ++---
.../Security Features/CWE-759/Sha1Utils.cs | 53 ++++++++
4 files changed, 230 insertions(+), 44 deletions(-)
create mode 100644 csharp/ql/test/experimental/Security Features/CWE-759/Sha1Utils.cs
diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
index 5ac93d3004a..8abdb5a527d 100644
--- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
+++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql
@@ -33,8 +33,9 @@ class KeyedHashAlgorithm extends RefType {
}
/**
- * The method `ComputeHash()`, `ComputeHashAsync`, `TryComputeHash`, `HashData`, or `TryHashData` declared in `System.Security.Cryptography.HashAlgorithm` and
- * the method `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
+ * The method `ComputeHash()`, `ComputeHashAsync`, `TryComputeHash`, `HashData`, or
+ * `TryHashData` declared in `System.Security.Cryptography.HashAlgorithm` and the method
+ * `HashData()` declared in `Windows.Security.Cryptography.Core.HashAlgorithmProvider`.
*/
class HashMethod extends Method {
HashMethod() {
@@ -46,8 +47,11 @@ class HashMethod extends Method {
}
}
-/** Gets a regular expression for matching common names of variables that indicate the value being held is a password. */
-string getPasswordRegex() { result = "(?i).*pass(wd|word|code|phrase).*" }
+/**
+ * Gets a regular expression for matching common names of variables that indicate the
+ * value being held is a password.
+ */
+string getPasswordRegex() { result = "(?i)pass(wd|word|code|phrase)" }
/** Finds variables that hold password information judging by their names. */
class PasswordVarExpr extends Expr {
@@ -56,21 +60,65 @@ class PasswordVarExpr extends Expr {
}
}
-/** Holds if there is another hashing method call. */
-predicate hasAnotherHashCall(MethodCall mc) {
- exists(Call mc2, DataFlow2::Node src, DataFlow2::Node sink |
- (
- mc2.getTarget() instanceof HashMethod or
- mc2.(ObjectCreation).getObjectType().getABaseType+() instanceof HashAlgorithm
- ) and
- mc2 != mc and
- src.asExpr() = mc.getAReachableElement() and
- sink.asExpr() = mc2.getAChildExpr() and
- TaintTracking2::localTaint(src, sink)
+/**
+ * Holds if `mc` is a hashing method call or invokes a hashing method call
+ * directly or indirectly.
+ */
+predicate isHashCall(MethodCall mc) {
+ mc.getTarget() instanceof HashMethod
+ or
+ exists(MethodCall mcc |
+ mc.getTarget().calls(mcc.getTarget()) and
+ isHashCall(mcc) and
+ DataFlow::localExprFlow(mc.getTarget().getAParameter().getAnAccess(), mcc.getAnArgument())
)
}
-/** Taint configuration tracking flow from an expression whose name suggests it holds password data to a method call that generates a hash without a salt. */
+/** Holds if there is another hashing method call. */
+predicate hasAnotherHashCall(MethodCall mc) {
+ exists(MethodCall mc2, DataFlow2::Node src, DataFlow2::Node sink |
+ isHashCall(mc2) and
+ mc2 != mc and
+ (
+ src.asExpr() = mc.getQualifier() or
+ src.asExpr() = mc.getAnArgument() or
+ src.asExpr() = mc
+ ) and
+ (
+ sink.asExpr() = mc2.getQualifier() or
+ sink.asExpr() = mc2.getAnArgument()
+ ) and
+ DataFlow::localFlow(src, sink)
+ )
+}
+
+/** Holds if a password hash without salt is further processed in another method call. */
+predicate hasFurtherProcessing(MethodCall mc) {
+ mc.getTarget().fromLibrary() and
+ (
+ mc.getTarget().hasQualifiedName("System.Array", "Copy") or // Array.Copy(passwordHash, 0, password.Length), 0, key, 0, keyLen);
+ mc.getTarget().hasQualifiedName("System.String", "Concat") or // string.Concat(passwordHash, saltkey)
+ mc.getTarget().hasQualifiedName("System.Buffer", "BlockCopy") or // Buffer.BlockCopy(passwordHash, 0, allBytes, 0, 20)
+ mc.getTarget().hasQualifiedName("System.String", "Format") // String.Format("{0}:{1}:{2}", username, salt, password)
+ )
+}
+
+/**
+ * Holds if `mc` is part of a call graph that satisfies `isHashCall` but is not at the
+ * top of the call hierarchy.
+ */
+predicate hasHashAncestor(MethodCall mc) {
+ exists(MethodCall mpc |
+ mpc.getTarget().calls(mc.getTarget()) and
+ isHashCall(mpc) and
+ DataFlow::localExprFlow(mpc.getTarget().getAParameter().getAnAccess(), mc.getAnArgument())
+ )
+}
+
+/**
+ * Taint configuration tracking flow from an expression whose name suggests it holds
+ * password data to a method call that generates a hash without a salt.
+ */
class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
HashWithoutSaltConfiguration() { this = "HashWithoutSaltConfiguration" }
@@ -79,8 +127,23 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc |
sink.asExpr() = mc.getArgument(0) and
- mc.getTarget() instanceof HashMethod and
- not hasAnotherHashCall(mc)
+ isHashCall(mc) and
+ not hasAnotherHashCall(mc) and
+ not hasHashAncestor(mc) and
+ not exists(MethodCall mmc |
+ hasFurtherProcessing(mmc) and
+ DataFlow::localExprFlow(mc, mmc.getAnArgument())
+ ) and
+ not exists(Call c |
+ (
+ c.getTarget().getDeclaringType().getABaseType*() instanceof HashAlgorithm or
+ c.getTarget()
+ .getDeclaringType()
+ .getABaseType*()
+ .hasQualifiedName("System.Security.Cryptography", "DeriveBytes")
+ ) and
+ DataFlow::localExprFlow(mc, c.getAnArgument())
+ )
)
}
@@ -104,13 +167,7 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
*/
override predicate isSanitizer(DataFlow::Node node) {
exists(MethodCall mc |
- mc.getTarget().fromLibrary() and
- (
- mc.getTarget().hasQualifiedName("System.Array", "CopyTo") or // passBytes.CopyTo(rawSalted, 0)
- mc.getTarget().hasQualifiedName("System.String", "Concat") or // string.Concat(password, saltkey)
- mc.getTarget().hasQualifiedName("System.Buffer", "BlockCopy") or // Buffer.BlockCopy(salt, 0, allBytes, 0, 20)
- mc.getTarget().hasQualifiedName("System.String", "Format") // String.Format("{0}:{1}:{2}", username, salt, password)
- ) and
+ hasFurtherProcessing(mc) and
mc.getAnArgument() = node.asExpr()
)
or
@@ -118,12 +175,19 @@ class HashWithoutSaltConfiguration extends TaintTracking::Configuration {
or
exists(InterpolatedStringExpr e | node.asExpr() = e.getAnInsert())
or
+ exists(Call c |
+ c.getTarget()
+ .getDeclaringType()
+ .getABaseType*()
+ .hasQualifiedName("System.Security.Cryptography", "DeriveBytes")
+ )
+ or
// a salt or key is included in subclasses of `KeyedHashAlgorithm`
- exists(MethodCall mc, Assignment ass, ObjectCreation oc |
- ass.getRValue() = oc and
+ exists(MethodCall mc, Assignment a, ObjectCreation oc |
+ a.getRValue() = oc and
oc.getObjectType().getABaseType+() instanceof KeyedHashAlgorithm and
mc.getTarget() instanceof HashMethod and
- ass.getLValue() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and
+ a.getLValue() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and
mc.getArgument(0) = node.asExpr()
)
}
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
index f2278519de0..302936c0ea6 100644
--- a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.cs
@@ -1,6 +1,7 @@
// semmle-extractor-options: /r:System.Security.Cryptography.Primitives.dll /r:System.Security.Cryptography.Csp.dll /r:System.Security.Cryptography.Algorithms.dll
using System;
+using System.Text;
using System.Security.Cryptography;
using Windows.Security.Cryptography;
@@ -130,4 +131,72 @@ public class Test
}
return hmacbytes;
}
+
+ private byte[] TryDecrypt(byte[] buffer, int offset, int length, byte[] password, int keyLen) {
+ byte[] key = new byte[16];
+ Array.Copy(SHA1.Create().ComputeHash(password, 0, password.Length), 0, key, 0, keyLen);
+ byte[] ret = Aes.Create().CreateDecryptor(key, null).TransformFinalBlock(buffer, offset, length);
+ return ret;
+ }
+
+ // GOOD - Use password hash without a salt having further processing.
+ public byte[] encrypt(byte[] pass, byte[] salt, byte[] blob) {
+ byte[] key = new byte[salt.Length + pass.Length];
+ Array.Copy(salt, 0, key, 0, salt.Length);
+ Array.Copy(pass, 0, key, salt.Length, pass.Length);
+ byte[] pkb = TryDecrypt(blob, 8, blob.Length - 8, key, 16);
+ return pkb;
+ }
+
+ public string CreatePasswordHash(string password, string saltkey)
+ {
+ var saltAndPassword = string.Concat(password, saltkey);
+ HashAlgorithm algorithm = SHA256.Create();
+ var hashByteArray = algorithm.ComputeHash(Encoding.UTF8.GetBytes(saltAndPassword));
+ return BitConverter.ToString(hashByteArray).Replace("-", "");
+ }
+
+ private string GetMD5HashBinHex (string toBeHashed)
+ {
+ MD5 hash = MD5.Create ();
+ byte[] result = hash.ComputeHash (Encoding.ASCII.GetBytes (toBeHashed));
+
+ StringBuilder sb = new StringBuilder ();
+ foreach (byte b in result)
+ sb.Append (b.ToString ("x2"));
+
+ return sb.ToString ();
+ }
+
+ // GOOD: Password concatenated with other information before hashing
+ public string CreatePasswordHash2(string username, string realm, string password)
+ {
+ string A1 = String.Format ("{0}:{1}:{2}", username, realm, password);
+
+ string HA1 = GetMD5HashBinHex (A1);
+ return HA1;
+ }
+
+ private byte[] Xor(byte[] array1, byte[] array2) {
+ var result = new byte[array1.Length];
+
+ for (int i = 0; i < array1.Length; i++) {
+ result[i] = (byte)(array1[i] ^ array2[i]);
+ }
+
+ return result;
+ }
+
+ // GOOD: Password hash without salt is further hashed with salt
+ public byte[] GetScrable(byte[] password, byte[] decodedSalt) {
+ var first20SaltBytes = new byte[20];
+ Array.Copy(decodedSalt, first20SaltBytes, 20);
+
+ var step1 = Sha1Utils.Hash(password);
+ var step2 = Sha1Utils.Hash(step1);
+ var step3 = Sha1Utils.Hash(first20SaltBytes, step2);
+ var scrambleBytes = Xor(step1, step3);
+
+ return scrambleBytes;
+ }
}
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
index 752c5912662..6238b0d5dc8 100644
--- a/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/HashWithoutSalt.expected
@@ -1,19 +1,19 @@
edges
-| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff |
-| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes |
-| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] |
-| HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes |
-| HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:18:70:18:77 | access to parameter password : String | HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff |
+| HashWithoutSalt.cs:38:28:38:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes |
+| HashWithoutSalt.cs:38:64:38:71 | access to parameter password : String | HashWithoutSalt.cs:38:28:38:72 | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:70:28:70:72 | call to method GetBytes : Byte[] | HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes |
+| HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | HashWithoutSalt.cs:70:28:70:72 | call to method GetBytes : Byte[] |
nodes
-| HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | semmle.label | access to parameter password : String |
-| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | semmle.label | access to local variable passBuff |
-| HashWithoutSalt.cs:37:28:37:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
-| HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | semmle.label | access to parameter password : String |
-| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | semmle.label | access to local variable passBytes |
-| HashWithoutSalt.cs:69:28:69:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
-| HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | semmle.label | access to parameter password : String |
-| HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | semmle.label | access to local variable passBytes |
+| HashWithoutSalt.cs:18:70:18:77 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | semmle.label | access to local variable passBuff |
+| HashWithoutSalt.cs:38:28:38:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:38:64:38:71 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | semmle.label | access to local variable passBytes |
+| HashWithoutSalt.cs:70:28:70:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
+| HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | semmle.label | access to parameter password : String |
+| HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | semmle.label | access to local variable passBytes |
#select
-| HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | HashWithoutSalt.cs:17:70:17:77 | access to parameter password : String | HashWithoutSalt.cs:19:49:19:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:17:70:17:77 | access to parameter password | The password |
-| HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | HashWithoutSalt.cs:37:64:37:71 | access to parameter password : String | HashWithoutSalt.cs:38:51:38:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:37:64:37:71 | access to parameter password | The password |
-| HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | HashWithoutSalt.cs:69:64:69:71 | access to parameter password : String | HashWithoutSalt.cs:70:48:70:56 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:69:64:69:71 | access to parameter password | The password |
+| HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | HashWithoutSalt.cs:18:70:18:77 | access to parameter password : String | HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:18:70:18:77 | access to parameter password | The password |
+| HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | HashWithoutSalt.cs:38:64:38:71 | access to parameter password : String | HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:38:64:38:71 | access to parameter password | The password |
+| HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:70:64:70:71 | access to parameter password | The password |
diff --git a/csharp/ql/test/experimental/Security Features/CWE-759/Sha1Utils.cs b/csharp/ql/test/experimental/Security Features/CWE-759/Sha1Utils.cs
new file mode 100644
index 00000000000..d29b6b2240b
--- /dev/null
+++ b/csharp/ql/test/experimental/Security Features/CWE-759/Sha1Utils.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+internal static class Sha1Utils
+{
+ public static byte[] Hash(string str)
+ {
+ var bytes = str == null ? new byte[0] : Encoding.UTF8.GetBytes(str);
+
+ return Hash(bytes);
+ }
+
+ public static byte[] Hash(byte[] bytes)
+ {
+ var sha1 = SHA1.Create();
+ var hashBytes = sha1.ComputeHash(bytes);
+
+ return hashBytes;
+ }
+
+ public static string HexStringFromBytes(byte[] bytes)
+ {
+ var sb = new StringBuilder();
+ foreach (var b in bytes)
+ {
+ var hex = b.ToString("x2");
+ sb.Append(hex);
+ }
+ return sb.ToString();
+ }
+
+ public static byte[] Hash(byte[] salt, byte[] str)
+ {
+ var salted = new byte[salt.Length + str.Length];
+ Array.Copy(salt, salted, salt.Length);
+ Array.Copy(str, 0, salted, salt.Length, str.Length);
+
+ return Hash(salted);
+ }
+
+ public static byte[] Xor(byte[] array1, byte[] array2)
+ {
+ var result = new byte[array1.Length];
+
+ for (int i = 0; i < array1.Length; i++)
+ {
+ result[i] = (byte)(array1[i] ^ array2[i]);
+ }
+
+ return result;
+ }
+}
From 8bcffc2886f3c17d6083287d4177f053683e36db Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Thu, 2 Dec 2021 04:00:29 +0000
Subject: [PATCH 007/296] Query to detect unsafe request dispatcher usage
---
.../semmle/code/java/frameworks/Servlets.qll | 24 +++
.../CWE/CWE-552/UnsafeRequestPath.java | 30 ++++
.../CWE-552/UnsafeServletRequestDispatch.java | 82 ++++++++++
.../CWE/CWE-552/UnsafeUrlForward.qhelp | 26 ++-
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 148 ++++++++++++++++--
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 29 +++-
.../security/CWE-552/UnsafeRequestPath.java | 52 ++++++
.../CWE-552/UnsafeServletRequestDispatch.java | 128 +++++++++++++++
.../CWE-552/UnsafeUrlForward.expected | 32 ++++
.../security/CWE-552/UnsafeUrlForward.java | 11 ++
.../servlet/http/HttpServletRequest.java | 2 +
11 files changed, 543 insertions(+), 21 deletions(-)
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
create mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeRequestPath.java
create mode 100644 java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
index 76c82b37786..2ab2c62c4d4 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
@@ -347,3 +347,27 @@ predicate isRequestGetParamMethod(MethodAccess ma) {
ma.getMethod() instanceof ServletRequestGetParameterMapMethod or
ma.getMethod() instanceof HttpServletRequestGetQueryStringMethod
}
+
+/** The Java EE RequestDispatcher. */
+library class RequestDispatcher extends RefType {
+ RequestDispatcher() {
+ this.hasQualifiedName(["javax.servlet", "jakarta.servlet"], "RequestDispatcher") or
+ this.hasQualifiedName("javax.portlet", "PortletRequestDispatcher")
+ }
+}
+
+/** The `getRequestDispatcher` method. */
+library class GetRequestDispatcherMethod extends Method {
+ GetRequestDispatcherMethod() {
+ this.getReturnType() instanceof RequestDispatcher and
+ this.getName() = "getRequestDispatcher"
+ }
+}
+
+/** The request dispatch method. */
+library class RequestDispatchMethod extends Method {
+ RequestDispatchMethod() {
+ this.getDeclaringType() instanceof RequestDispatcher and
+ this.hasName(["forward", "include"])
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
new file mode 100644
index 00000000000..ffa0ddf63bd
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
@@ -0,0 +1,30 @@
+public class UnsafeRequestPath implements Filter {
+ private static final String BASE_PATH = "/pages";
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ {
+ // BAD: Request dispatcher from servlet path without check
+ String path = ((HttpServletRequest) request).getServletPath();
+ // A sample payload "/%57EB-INF/web.xml" can bypass this `startsWith` check
+ if (path != null && !path.startsWith("/WEB-INF")) {
+ request.getRequestDispatcher(path).forward(request, response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ {
+ // GOOD: Request dispatcher from servlet path with path traversal check
+ String path = ((HttpServletRequest) request).getServletPath();
+
+ if (path.startsWith(BASE_PATH) && !path.contains("..")) {
+ request.getRequestDispatcher(path).forward(request, response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
new file mode 100644
index 00000000000..042a188c4c7
--- /dev/null
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
@@ -0,0 +1,82 @@
+public class UnsafeServletRequestDispatch extends HttpServlet {
+ private static final String BASE_PATH = "/pages";
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ {
+ // GOOD: whitelisted URI
+ if (action.equals("Login")) {
+ ServletContext sc = cfg.getServletContext();
+ RequestDispatcher rd = sc.getRequestDispatcher("/Login.jsp");
+ rd.forward(request, response);
+ }
+ }
+
+ {
+ // BAD: Request dispatcher constructed from `ServletContext` without input validation
+ String returnURL = request.getParameter("returnURL");
+ ServletConfig cfg = getServletConfig();
+
+ ServletContext sc = cfg.getServletContext();
+ RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
+ rd.forward(request, response);
+ }
+
+ {
+ // BAD: Request dispatcher without path traversal check
+ String path = request.getParameter("path");
+
+ // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
+ // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
+ if (path.startsWith(BASE_PATH)) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+ }
+
+ {
+ // GOOD: Request dispatcher with path traversal check
+ String path = request.getParameter("path");
+
+ if (path.startsWith(BASE_PATH) && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+
+ {
+ // GOOD: Request dispatcher with path normalization
+ String path = request.getParameter("path");
+ Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
+
+ // /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
+ // /pages/welcome.jsp/../../%57EB-INF/web.xml becomes /%57EB-INF/web.xml
+ if (requestedPath.startsWith(BASE_PATH)) {
+ request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
+ }
+ }
+
+ {
+ // BAD: Request dispatcher with improper negation check and without url decoding
+ String path = request.getParameter("path");
+ Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
+
+ if (!requestedPath.startsWith("/WEB-INF") && !requestedPath.startsWith("/META-INF")) {
+ request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
+ }
+ }
+
+ {
+ // GOOD: Request dispatcher with path traversal check and url decoding
+ String path = request.getParameter("path");
+ boolean hasEncoding = path.contains("%");
+ while (hasEncoding) {
+ path = URLDecoder.decode(path, "UTF-8");
+ hasEncoding = path.contains("%");
+ }
+
+ if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
index 572b14bb02f..8daef391db8 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
@@ -5,27 +5,45 @@
-Constructing a server-side redirect path with user input could allow an attacker to download application binaries
+
Constructing a server-side redirect path with user input could allow an attacker to download application binaries
(including application classes or jar files) or view arbitrary files within protected directories.
-In order to prevent untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.
+Unsanitized user provided data must not be used to construct the path for URL forwarding. In order to prevent
+untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.
+
The following examples show the bad case and the good case respectively.
The bad methods show an HTTP request parameter being used directly in a URL forward
-without validating the input, which may cause file leakage. In good1 method,
+without validating the input, which may cause file leakage. In good1 method,
ordinary forwarding requests are shown, which will not cause file leakage.
+The following examples show an HTTP request parameter or request path being used directly in a
+request dispatcher of Java EE without validating the input, which allows sensitive file exposure
+attacks. It also shows how to remedy the problem by validating the user input.
+
+
+
+
+
-File Disclosure: Unsafe Url Forward .
+File Disclosure:
+ Unsafe Url Forward .
+
+Jakarta Javadoc:
+ Security vulnerability with unsafe usage of RequestDispatcher .
+
+Micro Focus:
+ File Disclosure: J2EE
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index f9f13f72886..dd3b54de4c8 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -1,11 +1,11 @@
/**
- * @name Unsafe url forward from remote source
- * @description URL forward based on unvalidated user-input
+ * @name Unsafe url forward or dispatch from remote source
+ * @description URL forward or dispatch based on unvalidated user-input
* may cause file information disclosure.
* @kind path-problem
* @problem.severity error
* @precision high
- * @id java/unsafe-url-forward
+ * @id java/unsafe-url-forward-dispatch
* @tags security
* external/cwe-552
*/
@@ -14,20 +14,137 @@ import java
import UnsafeUrlForward
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets
+import semmle.code.java.controlflow.Guards
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
- }
+/**
+ * Holds if `ma` is a method call of matching with a path string, probably a whitelisted one.
+ */
+predicate isStringPathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().getName() = ["startsWith", "matches", "regionMatches"]
+}
- override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and branch = true
+/**
+ * Holds if `ma` is a method call of `java.nio.file.Path` which matches with another
+ * path, probably a whitelisted one.
+ */
+predicate isFilePathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypePath and
+ ma.getMethod().getName() = "startsWith"
+}
+
+/**
+ * Holds if `ma` is a method call that checks an input doesn't match using the `!`
+ * logical negation expression.
+ */
+predicate checkNoPathMatch(MethodAccess ma) {
+ exists(LogNotExpr lne |
+ (isStringPathMatch(ma) or isFilePathMatch(ma)) and
+ lne.getExpr() = ma
+ )
+}
+
+/**
+ * Holds if `ma` is a method call to check special characters `..` used in path traversal.
+ */
+predicate isPathTraversalCheck(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName(["contains", "indexOf"]) and
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
+}
+
+/**
+ * Holds if `ma` is a method call to decode a url string or check url encoding.
+ */
+predicate isPathDecoding(MethodAccess ma) {
+ // Search the special character `%` used in url encoding
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName(["contains", "indexOf"]) and
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
+ or
+ // Call to `URLDecoder` assuming the implementation handles double encoding correctly
+ ma.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
+ ma.getMethod().hasName("decode")
+}
+
+private class PathMatchSanitizer extends DataFlow::Node {
+ PathMatchSanitizer() {
+ exists(MethodAccess ma |
+ (
+ isStringPathMatch(ma) and
+ exists(MethodAccess ma2 |
+ isPathTraversalCheck(ma2) and
+ ma.getQualifier().(VarAccess).getVariable().getAnAccess() = ma2.getQualifier()
+ )
+ or
+ isFilePathMatch(ma)
+ ) and
+ (
+ not checkNoPathMatch(ma)
+ or
+ // non-match check needs decoding e.g. !path.startsWith("/WEB-INF/") won't detect /%57EB-INF/web.xml, which will be decoded and served by RequestDispatcher
+ checkNoPathMatch(ma) and
+ exists(MethodAccess ma2 |
+ isPathDecoding(ma2) and
+ ma.getQualifier().(VarAccess).getVariable().getAnAccess() = ma2.getQualifier()
+ )
+ ) and
+ this.asExpr() = ma.getQualifier()
+ )
}
}
+/**
+ * Holds if `ma` is a method call to check string content, which means an input string is not
+ * blindly trusted and helps to reduce FPs.
+ */
+predicate checkStringContent(MethodAccess ma, Expr expr) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod()
+ .hasName([
+ "charAt", "contains", "equals", "equalsIgnoreCase", "getBytes", "getChars", "indexOf",
+ "lastIndexOf", "length", "matches", "regionMatches", "replace", "replaceAll",
+ "replaceFirst", "substring"
+ ]) and
+ expr = ma.getQualifier()
+ or
+ (
+ ma.getMethod().getDeclaringType() instanceof TypeStringBuffer or
+ ma.getMethod().getDeclaringType() instanceof TypeStringBuilder
+ ) and
+ expr = ma.getAnArgument()
+}
+
+private class StringOperationSanitizer extends DataFlow::Node {
+ StringOperationSanitizer() { exists(MethodAccess ma | checkStringContent(ma, this.asExpr())) }
+}
+
+/**
+ * Holds if `expr` is an expression returned from null or empty string check.
+ */
+predicate isNullOrEmptyCheck(Expr expr) {
+ exists(ConditionBlock cb, ReturnStmt rt |
+ cb.controls(rt.getBasicBlock(), true) and
+ (
+ cb.getCondition().(EQExpr).getAnOperand() instanceof NullLiteral // if (path == null)
+ or
+ // if (path.equals(""))
+ exists(MethodAccess ma |
+ cb.getCondition() = ma and
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName("equals") and
+ ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = ""
+ )
+ ) and
+ expr.getParent+() = rt
+ )
+}
+
+private class NullOrEmptyCheckSanitizer extends DataFlow::Node {
+ NullOrEmptyCheckSanitizer() { isNullOrEmptyCheck(this.asExpr()) }
+}
+
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
@@ -45,11 +162,12 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink }
- override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
- guard instanceof StartsWithSanitizer
+ override predicate isSanitizer(DataFlow::Node node) {
+ node instanceof UnsafeUrlForwardSanitizer or
+ node instanceof PathMatchSanitizer or
+ node instanceof StringOperationSanitizer or
+ node instanceof NullOrEmptyCheckSanitizer
}
-
- override predicate isSanitizer(DataFlow::Node node) { node instanceof UnsafeUrlForwardSanitizer }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeUrlForwardFlowConfig conf
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index f2656316203..ab15549b9e1 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -32,11 +32,11 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
-/** An argument to `ServletRequest.getRequestDispatcher`. */
+/** An argument to `getRequestDispatcher`. */
private class RequestDispatcherSink extends UnsafeUrlForwardSink {
RequestDispatcherSink() {
exists(MethodAccess ma |
- ma.getMethod() instanceof ServletRequestGetRequestDispatcherMethod and
+ ma.getMethod() instanceof GetRequestDispatcherMethod and
ma.getArgument(0) = this.asExpr()
)
}
@@ -70,3 +70,28 @@ private class SpringUrlForwardSink extends UnsafeUrlForwardSink {
this.asExpr() = any(ForwardPrefix fp).getAnAppendedExpression()
}
}
+
+/** Source model of remote flow source from `getServletPath`. */
+private class ServletGetPathSource extends SourceModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "javax.servlet.http;HttpServletRequest;true;getServletPath;;;ReturnValue;remote",
+ "jakarta.servlet.http;HttpServletRequest;true;getServletPath;;;ReturnValue;remote"
+ ]
+ }
+}
+
+/** Taint model related to `java.nio.file.Path`. */
+private class FilePathFlowStep extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "java.nio.file;Paths;true;get;;;Argument[-1];ReturnValue;taint",
+ "java.nio.file;Path;true;resolve;;;Argument[0];ReturnValue;taint",
+ "java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint",
+ "java.nio.file;Path;true;startsWith;;;Argument[-1];ReturnValue;taint",
+ "java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint"
+ ]
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeRequestPath.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeRequestPath.java
new file mode 100644
index 00000000000..2de0cae0d3c
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeRequestPath.java
@@ -0,0 +1,52 @@
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+// @WebFilter("/*")
+public class UnsafeRequestPath implements Filter {
+ private static final String BASE_PATH = "/pages";
+
+ @Override
+ // BAD: Request dispatcher from servlet path without check
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ String path = ((HttpServletRequest) request).getServletPath();
+ // A sample payload "/%57EB-INF/web.xml" can bypass this `startsWith` check
+ if (path != null && !path.startsWith("/WEB-INF")) {
+ request.getRequestDispatcher(path).forward(request, response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ // GOOD: Request dispatcher from servlet path with check
+ public void doFilter2(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ String path = ((HttpServletRequest) request).getServletPath();
+
+ if (path.startsWith(BASE_PATH) && !path.contains("..")) {
+ request.getRequestDispatcher(path).forward(request, response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+
+ // GOOD: Request dispatcher from servlet path with whitelisted string comparison
+ public void doFilter3(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ String path = ((HttpServletRequest) request).getServletPath();
+
+ if (path.equals("/comaction")) {
+ request.getRequestDispatcher(path).forward(request, response);
+ } else {
+ chain.doFilter(request, response);
+ }
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
new file mode 100644
index 00000000000..f0b0a71ea0f
--- /dev/null
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
@@ -0,0 +1,128 @@
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+public class UnsafeServletRequestDispatch extends HttpServlet {
+ private static final String BASE_PATH = "/pages";
+
+ @Override
+ // BAD: Request dispatcher constructed from `ServletContext` without input validation
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String action = request.getParameter("action");
+ String returnURL = request.getParameter("returnURL");
+
+ ServletConfig cfg = getServletConfig();
+ if (action.equals("Login")) {
+ ServletContext sc = cfg.getServletContext();
+ RequestDispatcher rd = sc.getRequestDispatcher("/Login.jsp");
+ rd.forward(request, response);
+ } else {
+ ServletContext sc = cfg.getServletContext();
+ RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
+ rd.forward(request, response);
+ }
+ }
+
+ @Override
+ // BAD: Request dispatcher constructed from `HttpServletRequest` without input validation
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String action = request.getParameter("action");
+ String returnURL = request.getParameter("returnURL");
+
+ if (action.equals("Login")) {
+ RequestDispatcher rd = request.getRequestDispatcher("/Login.jsp");
+ rd.forward(request, response);
+ } else {
+ RequestDispatcher rd = request.getRequestDispatcher(returnURL);
+ rd.forward(request, response);
+ }
+ }
+
+ @Override
+ // GOOD: Request dispatcher with a whitelisted URI
+ protected void doPut(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String action = request.getParameter("action");
+
+ if (action.equals("Login")) {
+ RequestDispatcher rd = request.getRequestDispatcher("/Login.jsp");
+ rd.forward(request, response);
+ } else if (action.equals("Register")) {
+ RequestDispatcher rd = request.getRequestDispatcher("/Register.jsp");
+ rd.forward(request, response);
+ }
+ }
+
+ // BAD: Request dispatcher without path traversal check
+ protected void doHead2(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String path = request.getParameter("path");
+
+ // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
+ // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
+ if (path.startsWith(BASE_PATH)) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+
+ // GOOD: Request dispatcher with path traversal check
+ protected void doHead3(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String path = request.getParameter("path");
+
+ if (path.startsWith(BASE_PATH) && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+
+ // GOOD: Request dispatcher with path normalization and comparison
+ protected void doHead4(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String path = request.getParameter("path");
+ Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
+
+ // /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
+ // /pages/welcome.jsp/../../%57EB-INF/web.xml becomes /%57EB-INF/web.xml
+ if (requestedPath.startsWith(BASE_PATH)) {
+ request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
+ }
+ }
+
+ // BAD: Request dispatcher with improper negation check and without url decoding
+ protected void doHead5(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String path = request.getParameter("path");
+ Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
+
+ if (!requestedPath.startsWith("/WEB-INF") && !requestedPath.startsWith("/META-INF")) {
+ request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
+ }
+ }
+
+ // GOOD: Request dispatcher with path traversal check and url decoding
+ protected void doHead6(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ String path = request.getParameter("path");
+ boolean hasEncoding = path.contains("%");
+ while (hasEncoding) {
+ path = URLDecoder.decode(path, "UTF-8");
+ hasEncoding = path.contains("%");
+ }
+
+ if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+ }
+}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
index b70a131f93c..185508dfc57 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
@@ -1,4 +1,13 @@
edges
+| UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | UnsafeRequestPath.java:23:33:23:36 | path |
+| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL |
+| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL |
+| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:107:53:107:56 | path : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url |
| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url |
@@ -6,7 +15,22 @@ edges
| UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:61:31:63 | url |
| UnsafeUrlForward.java:36:19:36:28 | url : String | UnsafeUrlForward.java:38:33:38:35 | url |
| UnsafeUrlForward.java:47:19:47:28 | url : String | UnsafeUrlForward.java:49:33:49:62 | ... + ... |
+| UnsafeUrlForward.java:58:19:58:28 | url : String | UnsafeUrlForward.java:60:33:60:62 | ... + ... |
nodes
+| UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | semmle.label | getServletPath(...) : String |
+| UnsafeRequestPath.java:23:33:23:36 | path | semmle.label | path |
+| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | semmle.label | returnURL |
+| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | semmle.label | returnURL |
+| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:76:53:76:56 | path | semmle.label | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | semmle.label | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | semmle.label | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | semmle.label | path : String |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | semmle.label | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | semmle.label | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String |
@@ -20,8 +44,15 @@ nodes
| UnsafeUrlForward.java:38:33:38:35 | url | semmle.label | url |
| UnsafeUrlForward.java:47:19:47:28 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:49:33:49:62 | ... + ... | semmle.label | ... + ... |
+| UnsafeUrlForward.java:58:19:58:28 | url : String | semmle.label | url : String |
+| UnsafeUrlForward.java:60:33:60:62 | ... + ... | semmle.label | ... + ... |
subpaths
#select
+| UnsafeRequestPath.java:23:33:23:36 | path | UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) : String | UnsafeRequestPath.java:23:33:23:36 | path | Potentially untrusted URL forward due to $@. | UnsafeRequestPath.java:20:17:20:63 | getServletPath(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:76:53:76:56 | path | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) | user-provided value |
| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value |
| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value |
| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value |
@@ -29,3 +60,4 @@ subpaths
| UnsafeUrlForward.java:31:61:31:63 | url | UnsafeUrlForward.java:30:27:30:36 | url : String | UnsafeUrlForward.java:31:61:31:63 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:30:27:30:36 | url | user-provided value |
| UnsafeUrlForward.java:38:33:38:35 | url | UnsafeUrlForward.java:36:19:36:28 | url : String | UnsafeUrlForward.java:38:33:38:35 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:36:19:36:28 | url | user-provided value |
| UnsafeUrlForward.java:49:33:49:62 | ... + ... | UnsafeUrlForward.java:47:19:47:28 | url : String | UnsafeUrlForward.java:49:33:49:62 | ... + ... | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:47:19:47:28 | url | user-provided value |
+| UnsafeUrlForward.java:60:33:60:62 | ... + ... | UnsafeUrlForward.java:58:19:58:28 | url : String | UnsafeUrlForward.java:60:33:60:62 | ... + ... | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:58:19:58:28 | url | user-provided value |
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java
index 1e7ce3a97c5..4018ed28948 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.java
@@ -54,6 +54,17 @@ public class UnsafeUrlForward {
}
}
+ @GetMapping("/bad7")
+ public void bad7(String url, HttpServletRequest request, HttpServletResponse response) {
+ try {
+ request.getRequestDispatcher("/WEB-INF/jsp/" + url + ".jsp").forward(request, response);
+ } catch (ServletException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
@GetMapping("/good1")
public void good1(String url, HttpServletRequest request, HttpServletResponse response) {
try {
diff --git a/java/ql/test/stubs/servlet-api-2.4/javax/servlet/http/HttpServletRequest.java b/java/ql/test/stubs/servlet-api-2.4/javax/servlet/http/HttpServletRequest.java
index bc15d102eca..5767e07ca5b 100644
--- a/java/ql/test/stubs/servlet-api-2.4/javax/servlet/http/HttpServletRequest.java
+++ b/java/ql/test/stubs/servlet-api-2.4/javax/servlet/http/HttpServletRequest.java
@@ -25,6 +25,7 @@ package javax.servlet.http;
import java.util.Enumeration;
import javax.servlet.ServletRequest;
+import javax.servlet.ServletContext;
public interface HttpServletRequest extends ServletRequest {
public String getAuthType();
@@ -52,4 +53,5 @@ public interface HttpServletRequest extends ServletRequest {
public boolean isRequestedSessionIdFromCookie();
public boolean isRequestedSessionIdFromURL();
public boolean isRequestedSessionIdFromUrl();
+ public ServletContext getServletContext();
}
From 29ce0e9ef19a46bf756472b8a3956a19cda443be Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Wed, 15 Dec 2021 16:19:50 +0000
Subject: [PATCH 008/296] Add sanitizer for virtual method calls
---
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 20 ++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index dd3b54de4c8..f77acf99e84 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -145,6 +145,23 @@ private class NullOrEmptyCheckSanitizer extends DataFlow::Node {
NullOrEmptyCheckSanitizer() { isNullOrEmptyCheck(this.asExpr()) }
}
+/** Holds if `ma` is a virtual method call of Map::get or Object::toString. */
+predicate isVirtualMethod(MethodAccess ma, Expr expr) {
+ ma.getMethod().getDeclaringType() instanceof TypeObject and
+ ma.getMethod().hasName("toString") and
+ (expr = ma or expr = ma.getQualifier())
+ or
+ (
+ ma.getMethod().getDeclaringType().getASupertype*().hasQualifiedName("java.util", "Map") and
+ ma.getMethod().hasName(["get", "getOrDefault"])
+ ) and
+ (expr = ma or expr = ma.getAnArgument())
+}
+
+private class VirtualMethodSanitizer extends DataFlow::Node {
+ VirtualMethodSanitizer() { exists(MethodAccess ma | isVirtualMethod(ma, this.asExpr())) }
+}
+
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
@@ -166,7 +183,8 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
node instanceof UnsafeUrlForwardSanitizer or
node instanceof PathMatchSanitizer or
node instanceof StringOperationSanitizer or
- node instanceof NullOrEmptyCheckSanitizer
+ node instanceof NullOrEmptyCheckSanitizer or
+ node instanceof VirtualMethodSanitizer
}
}
From fed1d882680beea005089bdea3b50f3f1059706b Mon Sep 17 00:00:00 2001
From: haby0
Date: Mon, 20 Dec 2021 16:09:06 +0800
Subject: [PATCH 009/296] Add shutil module path injection sinks
---
.../lib/semmle/python/frameworks/Stdlib.qll | 91 +++++++++++++++++++
.../shutil_path_injection.py | 34 +++++++
2 files changed, 125 insertions(+)
create mode 100644 python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
index f54022c6bc7..3f73793762f 100644
--- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
@@ -2942,6 +2942,97 @@ private module StdlibPrivate {
]
}
}
+
+ // ---------------------------------------------------------------------------
+ // shutil
+ // ---------------------------------------------------------------------------
+ /** Gets a reference to the `shutil` module. */
+ private API::Node shutil() { result = API::moduleImport("shutil") }
+
+ /**
+ * A call to the `shutil.rmtree` function.
+ *
+ * See https://docs.python.org/3/library/shutil.html#shutil.rmtree
+ */
+ private class ShutilRmtreeCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
+ ShutilRmtreeCall() { this = shutil().getMember("rmtree").getACall() }
+
+ override DataFlow::Node getAPathArgument() {
+ result in [this.getArg(0), this.getArgByName("path")]
+ }
+ }
+
+ /**
+ * The `shutil` module provides methods to copy, move files or copy file attributes.
+ * See:
+ * - https://docs.python.org/3/library/shutil.html#shutil.copyfile
+ * - https://docs.python.org/3/library/shutil.html#shutil.copymode
+ * - https://docs.python.org/3/library/shutil.html#shutil.copystat
+ * - https://docs.python.org/3/library/shutil.html#shutil.copy
+ * - https://docs.python.org/3/library/shutil.html#shutil.copy2
+ * - https://docs.python.org/3/library/shutil.html#shutil.copytree
+ * - https://docs.python.org/3/library/shutil.html#shutil.move
+ */
+ private class ShutilCopyCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
+ ShutilCopyCall() {
+ this =
+ shutil()
+ .getMember([
+ // these are used to copy files
+ "copyfile", "copy", "copy2", "copytree",
+ // these are used to move files
+ "move",
+ // these are used to copy some attributes of the file
+ "copymode", "copystat"
+ ])
+ .getACall()
+ }
+
+ override DataFlow::Node getAPathArgument() {
+ result in [this.getArg(0), this.getArgByName("src"), this.getArg(1), this.getArgByName("dst")]
+ }
+ }
+
+ /**
+ * A call to the `shutil.copyfileobj` function.
+ *
+ * See https://docs.python.org/3/library/shutil.html#shutil.copyfileobj
+ */
+ private class ShutilCopyfileobjCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
+ ShutilCopyfileobjCall() { this = shutil().getMember("copyfileobj").getACall() }
+
+ override DataFlow::Node getAPathArgument() {
+ result in [
+ this.getArg(0), this.getArgByName("fsrc"), this.getArg(1), this.getArgByName("fdst")
+ ]
+ }
+ }
+
+ /**
+ * A call to the `shutil.disk_usage` function.
+ *
+ * See https://docs.python.org/3/library/shutil.html#shutil.disk_usage
+ */
+ private class ShutilDiskUsageCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
+ ShutilDiskUsageCall() { this = shutil().getMember("disk_usage").getACall() }
+
+ override DataFlow::Node getAPathArgument() {
+ result in [this.getArg(0), this.getArgByName("path")]
+ }
+ }
+
+ /**
+ * A call to the `shutil.chown` function.
+ *
+ * See https://docs.python.org/3/library/shutil.html#shutil.chown
+ */
+ private class ShutilChownCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
+ ShutilChownCall() { this = shutil().getMember("chown").getACall() }
+
+ override DataFlow::Node getAPathArgument() {
+ result in [this.getArg(0), this.getArgByName("path")]
+ }
+ }
}
// ---------------------------------------------------------------------------
diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
new file mode 100644
index 00000000000..ca445cb6ed8
--- /dev/null
+++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
@@ -0,0 +1,34 @@
+import shutil
+from flask import Flask, request
+app = Flask(__name__)
+
+STATIC_DIR = "/server/static/"
+
+@app.route("/shutil-path1")
+def path_injection1():
+ dir = request.args.get('dir', '')
+ shutil.rmtree(dir) # NOT OK
+
+@app.route("/shutil-path2")
+def path_injection2():
+ path1 = request.args.get('path1', '')
+ path2 = request.args.get('path2', '')
+ shutil.copyfile(path1, path2) # NOT OK
+
+@app.route("/shutil-path3")
+def path_injection3():
+ path1 = request.args.get('path1', '')
+ path2 = request.args.get('path2', '')
+ shutil.copy(path1, path2) # NOT OK
+
+@app.route("/shutil-path4")
+def path_injection4():
+ path1 = request.args.get('path1', '')
+ path2 = request.args.get('path2', '')
+ shutil.move(path1, path2) # NOT OK
+
+@app.route("/shutil-path4")
+def path_injection5():
+ path1 = request.args.get('path1', '')
+ path2 = request.args.get('path2', '')
+ shutil.copymode(path1, path2) # NOT OK
\ No newline at end of file
From b4b91e84a3fee32f090a6f5285a9ace183208d2c Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 7 Dec 2021 18:24:00 +1300
Subject: [PATCH 010/296] Ruby: Fix ConstantAccessCfgNode.getValueText
The superclass definition uses SSA, which doesn't track constants.
---
ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 455327ddb0d..5ea3038c3a4 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -390,6 +390,8 @@ module ExprNodes {
/** Gets the scope expression. */
final ExprCfgNode getScopeExpr() { e.hasCfgChild(e.getScopeExpr(), this, result) }
+
+ override string getValueText() { result = this.getExpr().getValueText() }
}
private class StmtSequenceChildMapping extends ExprChildMapping, StmtSequence {
From 3df3fb092b7d22a32a83edc1f1e8e021fd805c3e Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 13 Dec 2021 12:15:45 +1300
Subject: [PATCH 011/296] Make room for new test code
This change is split over several commits so it is easier to see.
This change adds some extra lines, which will be populated in the next
commit.
---
ruby/ql/test/library-tests/ast/Ast.expected | 618 +++++-----
.../library-tests/ast/AstDesugar.expected | 208 ++--
.../test/library-tests/ast/ValueText.expected | 237 ++--
.../ast/literals/literals.expected | 1072 ++++++++---------
.../library-tests/ast/literals/literals.rb | 4 +
5 files changed, 1074 insertions(+), 1065 deletions(-)
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 1fa6cf4a4c3..e3630cf4ac2 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -1515,346 +1515,346 @@ literals/literals.rb:
# 66| getStmt: [AddExpr] ... + ...
# 66| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 66| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 9
-# 69| getStmt: [CharacterLiteral] ?x
-# 70| getStmt: [CharacterLiteral] ?\n
-# 71| getStmt: [CharacterLiteral] ?\s
-# 72| getStmt: [CharacterLiteral] ?\\
-# 73| getStmt: [CharacterLiteral] ?\u{58}
-# 74| getStmt: [CharacterLiteral] ?\C-a
-# 75| getStmt: [CharacterLiteral] ?\M-a
-# 76| getStmt: [CharacterLiteral] ?\M-\C-a
-# 77| getStmt: [CharacterLiteral] ?\C-\M-a
-# 80| getStmt: [SymbolLiteral] :""
-# 81| getStmt: [SymbolLiteral] :hello
-# 82| getStmt: [SymbolLiteral] :"foo bar"
-# 82| getComponent: [StringTextComponent] foo bar
-# 83| getStmt: [SymbolLiteral] :"bar baz"
-# 83| getComponent: [StringTextComponent] bar baz
-# 84| getStmt: [HashLiteral] {...}
-# 84| getElement: [Pair] Pair
-# 84| getKey: [SymbolLiteral] :foo
-# 84| getValue: [StringLiteral] "bar"
-# 84| getComponent: [StringTextComponent] bar
-# 85| getStmt: [SymbolLiteral] :"wibble"
-# 85| getComponent: [StringTextComponent] wibble
-# 86| getStmt: [SymbolLiteral] :"wibble wobble"
-# 86| getComponent: [StringTextComponent] wibble wobble
-# 87| getStmt: [SymbolLiteral] :"foo_#{...}"
-# 87| getComponent: [StringTextComponent] foo_
-# 87| getComponent: [StringInterpolationComponent] #{...}
-# 87| getStmt: [AddExpr] ... + ...
-# 87| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 87| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 88| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
-# 88| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
-# 89| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
-# 89| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
-# 92| getStmt: [ArrayLiteral] [...]
-# 93| getStmt: [ArrayLiteral] [...]
-# 93| getElement: [IntegerLiteral] 1
-# 93| getElement: [IntegerLiteral] 2
-# 93| getElement: [IntegerLiteral] 3
-# 94| getStmt: [ArrayLiteral] [...]
-# 94| getElement: [IntegerLiteral] 4
-# 94| getElement: [IntegerLiteral] 5
-# 94| getElement: [DivExpr] ... / ...
-# 94| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 12
-# 94| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 95| getStmt: [ArrayLiteral] [...]
-# 95| getElement: [IntegerLiteral] 7
-# 95| getElement: [ArrayLiteral] [...]
-# 95| getElement: [IntegerLiteral] 8
-# 95| getElement: [IntegerLiteral] 9
-# 98| getStmt: [ArrayLiteral] %w(...)
-# 99| getStmt: [ArrayLiteral] %w(...)
-# 99| getElement: [StringLiteral] "foo"
-# 99| getComponent: [StringTextComponent] foo
-# 99| getElement: [StringLiteral] "bar"
-# 99| getComponent: [StringTextComponent] bar
-# 99| getElement: [StringLiteral] "baz"
-# 99| getComponent: [StringTextComponent] baz
-# 100| getStmt: [ArrayLiteral] %w(...)
-# 100| getElement: [StringLiteral] "foo"
-# 100| getComponent: [StringTextComponent] foo
-# 100| getElement: [StringLiteral] "bar"
-# 100| getComponent: [StringTextComponent] bar
-# 100| getElement: [StringLiteral] "baz"
-# 100| getComponent: [StringTextComponent] baz
-# 101| getStmt: [ArrayLiteral] %w(...)
-# 101| getElement: [StringLiteral] "foo"
-# 101| getComponent: [StringTextComponent] foo
-# 101| getElement: [StringLiteral] "bar#{...}"
-# 101| getComponent: [StringTextComponent] bar
-# 101| getComponent: [StringInterpolationComponent] #{...}
-# 101| getStmt: [AddExpr] ... + ...
-# 101| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 101| getElement: [StringLiteral] "baz"
-# 101| getComponent: [StringTextComponent] baz
+# 73| getStmt: [CharacterLiteral] ?x
+# 74| getStmt: [CharacterLiteral] ?\n
+# 75| getStmt: [CharacterLiteral] ?\s
+# 76| getStmt: [CharacterLiteral] ?\\
+# 77| getStmt: [CharacterLiteral] ?\u{58}
+# 78| getStmt: [CharacterLiteral] ?\C-a
+# 79| getStmt: [CharacterLiteral] ?\M-a
+# 80| getStmt: [CharacterLiteral] ?\M-\C-a
+# 81| getStmt: [CharacterLiteral] ?\C-\M-a
+# 84| getStmt: [SymbolLiteral] :""
+# 85| getStmt: [SymbolLiteral] :hello
+# 86| getStmt: [SymbolLiteral] :"foo bar"
+# 86| getComponent: [StringTextComponent] foo bar
+# 87| getStmt: [SymbolLiteral] :"bar baz"
+# 87| getComponent: [StringTextComponent] bar baz
+# 88| getStmt: [HashLiteral] {...}
+# 88| getElement: [Pair] Pair
+# 88| getKey: [SymbolLiteral] :foo
+# 88| getValue: [StringLiteral] "bar"
+# 88| getComponent: [StringTextComponent] bar
+# 89| getStmt: [SymbolLiteral] :"wibble"
+# 89| getComponent: [StringTextComponent] wibble
+# 90| getStmt: [SymbolLiteral] :"wibble wobble"
+# 90| getComponent: [StringTextComponent] wibble wobble
+# 91| getStmt: [SymbolLiteral] :"foo_#{...}"
+# 91| getComponent: [StringTextComponent] foo_
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [AddExpr] ... + ...
+# 91| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 91| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
+# 92| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
+# 92| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
+# 93| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
+# 93| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
+# 96| getStmt: [ArrayLiteral] [...]
+# 97| getStmt: [ArrayLiteral] [...]
+# 97| getElement: [IntegerLiteral] 1
+# 97| getElement: [IntegerLiteral] 2
+# 97| getElement: [IntegerLiteral] 3
+# 98| getStmt: [ArrayLiteral] [...]
+# 98| getElement: [IntegerLiteral] 4
+# 98| getElement: [IntegerLiteral] 5
+# 98| getElement: [DivExpr] ... / ...
+# 98| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 12
+# 98| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
+# 99| getStmt: [ArrayLiteral] [...]
+# 99| getElement: [IntegerLiteral] 7
+# 99| getElement: [ArrayLiteral] [...]
+# 99| getElement: [IntegerLiteral] 8
+# 99| getElement: [IntegerLiteral] 9
# 102| getStmt: [ArrayLiteral] %w(...)
-# 102| getElement: [StringLiteral] "foo"
-# 102| getComponent: [StringTextComponent] foo
-# 102| getElement: [StringLiteral] "bar#{1+1}"
-# 102| getComponent: [StringTextComponent] bar#{1+1}
-# 102| getElement: [StringLiteral] "baz"
-# 102| getComponent: [StringTextComponent] baz
-# 105| getStmt: [ArrayLiteral] %i(...)
-# 106| getStmt: [ArrayLiteral] %i(...)
-# 106| getElement: [SymbolLiteral] :"foo"
+# 103| getStmt: [ArrayLiteral] %w(...)
+# 103| getElement: [StringLiteral] "foo"
+# 103| getComponent: [StringTextComponent] foo
+# 103| getElement: [StringLiteral] "bar"
+# 103| getComponent: [StringTextComponent] bar
+# 103| getElement: [StringLiteral] "baz"
+# 103| getComponent: [StringTextComponent] baz
+# 104| getStmt: [ArrayLiteral] %w(...)
+# 104| getElement: [StringLiteral] "foo"
+# 104| getComponent: [StringTextComponent] foo
+# 104| getElement: [StringLiteral] "bar"
+# 104| getComponent: [StringTextComponent] bar
+# 104| getElement: [StringLiteral] "baz"
+# 104| getComponent: [StringTextComponent] baz
+# 105| getStmt: [ArrayLiteral] %w(...)
+# 105| getElement: [StringLiteral] "foo"
+# 105| getComponent: [StringTextComponent] foo
+# 105| getElement: [StringLiteral] "bar#{...}"
+# 105| getComponent: [StringTextComponent] bar
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [AddExpr] ... + ...
+# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getElement: [StringLiteral] "baz"
+# 105| getComponent: [StringTextComponent] baz
+# 106| getStmt: [ArrayLiteral] %w(...)
+# 106| getElement: [StringLiteral] "foo"
# 106| getComponent: [StringTextComponent] foo
-# 106| getElement: [SymbolLiteral] :"bar"
-# 106| getComponent: [StringTextComponent] bar
-# 106| getElement: [SymbolLiteral] :"baz"
+# 106| getElement: [StringLiteral] "bar#{1+1}"
+# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getElement: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
-# 107| getStmt: [ArrayLiteral] %i(...)
-# 107| getElement: [SymbolLiteral] :"foo"
-# 107| getComponent: [StringTextComponent] foo
-# 107| getElement: [SymbolLiteral] :"bar"
-# 107| getComponent: [StringTextComponent] bar
-# 107| getElement: [SymbolLiteral] :"baz"
-# 107| getComponent: [StringTextComponent] baz
-# 108| getStmt: [ArrayLiteral] %i(...)
-# 108| getElement: [SymbolLiteral] :"foo"
-# 108| getComponent: [StringTextComponent] foo
-# 108| getElement: [SymbolLiteral] :"bar#{...}"
-# 108| getComponent: [StringTextComponent] bar
-# 108| getComponent: [StringInterpolationComponent] #{...}
-# 108| getStmt: [AddExpr] ... + ...
-# 108| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 108| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
-# 108| getElement: [SymbolLiteral] :"baz"
-# 108| getComponent: [StringTextComponent] baz
# 109| getStmt: [ArrayLiteral] %i(...)
-# 109| getElement: [SymbolLiteral] :"foo"
-# 109| getComponent: [StringTextComponent] foo
-# 109| getElement: [SymbolLiteral] :"bar#{"
-# 109| getComponent: [StringTextComponent] bar#{
-# 109| getElement: [SymbolLiteral] :"2"
-# 109| getComponent: [StringTextComponent] 2
-# 109| getElement: [SymbolLiteral] :"+"
-# 109| getComponent: [StringTextComponent] +
-# 109| getElement: [SymbolLiteral] :"4"
-# 109| getComponent: [StringTextComponent] 4
-# 109| getElement: [SymbolLiteral] :"}"
-# 109| getComponent: [StringTextComponent] }
-# 109| getElement: [SymbolLiteral] :"baz"
-# 109| getComponent: [StringTextComponent] baz
-# 112| getStmt: [HashLiteral] {...}
-# 113| getStmt: [HashLiteral] {...}
-# 113| getElement: [Pair] Pair
-# 113| getKey: [SymbolLiteral] :foo
-# 113| getValue: [IntegerLiteral] 1
-# 113| getElement: [Pair] Pair
-# 113| getKey: [SymbolLiteral] :bar
-# 113| getValue: [IntegerLiteral] 2
-# 113| getElement: [Pair] Pair
-# 113| getKey: [StringLiteral] "baz"
-# 113| getComponent: [StringTextComponent] baz
-# 113| getValue: [IntegerLiteral] 3
-# 114| getStmt: [HashLiteral] {...}
-# 114| getElement: [Pair] Pair
-# 114| getKey: [SymbolLiteral] :foo
-# 114| getValue: [IntegerLiteral] 7
-# 114| getElement: [HashSplatExpr] ** ...
-# 114| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
-# 114| getReceiver: [Self, SelfVariableAccess] self
-# 117| getStmt: [ParenthesizedExpr] ( ... )
-# 117| getStmt: [RangeLiteral] _ .. _
-# 117| getBegin: [IntegerLiteral] 1
-# 117| getEnd: [IntegerLiteral] 10
-# 118| getStmt: [ParenthesizedExpr] ( ... )
-# 118| getStmt: [RangeLiteral] _ ... _
-# 118| getBegin: [IntegerLiteral] 1
-# 118| getEnd: [IntegerLiteral] 10
-# 119| getStmt: [ParenthesizedExpr] ( ... )
-# 119| getStmt: [RangeLiteral] _ .. _
-# 119| getBegin: [IntegerLiteral] 1
-# 119| getEnd: [IntegerLiteral] 0
-# 120| getStmt: [ParenthesizedExpr] ( ... )
-# 120| getStmt: [RangeLiteral] _ .. _
-# 120| getBegin: [MethodCall] call to start
-# 120| getReceiver: [Self, SelfVariableAccess] self
-# 120| getEnd: [AddExpr] ... + ...
-# 120| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 120| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 3
+# 110| getStmt: [ArrayLiteral] %i(...)
+# 110| getElement: [SymbolLiteral] :"foo"
+# 110| getComponent: [StringTextComponent] foo
+# 110| getElement: [SymbolLiteral] :"bar"
+# 110| getComponent: [StringTextComponent] bar
+# 110| getElement: [SymbolLiteral] :"baz"
+# 110| getComponent: [StringTextComponent] baz
+# 111| getStmt: [ArrayLiteral] %i(...)
+# 111| getElement: [SymbolLiteral] :"foo"
+# 111| getComponent: [StringTextComponent] foo
+# 111| getElement: [SymbolLiteral] :"bar"
+# 111| getComponent: [StringTextComponent] bar
+# 111| getElement: [SymbolLiteral] :"baz"
+# 111| getComponent: [StringTextComponent] baz
+# 112| getStmt: [ArrayLiteral] %i(...)
+# 112| getElement: [SymbolLiteral] :"foo"
+# 112| getComponent: [StringTextComponent] foo
+# 112| getElement: [SymbolLiteral] :"bar#{...}"
+# 112| getComponent: [StringTextComponent] bar
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [AddExpr] ... + ...
+# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getElement: [SymbolLiteral] :"baz"
+# 112| getComponent: [StringTextComponent] baz
+# 113| getStmt: [ArrayLiteral] %i(...)
+# 113| getElement: [SymbolLiteral] :"foo"
+# 113| getComponent: [StringTextComponent] foo
+# 113| getElement: [SymbolLiteral] :"bar#{"
+# 113| getComponent: [StringTextComponent] bar#{
+# 113| getElement: [SymbolLiteral] :"2"
+# 113| getComponent: [StringTextComponent] 2
+# 113| getElement: [SymbolLiteral] :"+"
+# 113| getComponent: [StringTextComponent] +
+# 113| getElement: [SymbolLiteral] :"4"
+# 113| getComponent: [StringTextComponent] 4
+# 113| getElement: [SymbolLiteral] :"}"
+# 113| getComponent: [StringTextComponent] }
+# 113| getElement: [SymbolLiteral] :"baz"
+# 113| getComponent: [StringTextComponent] baz
+# 116| getStmt: [HashLiteral] {...}
+# 117| getStmt: [HashLiteral] {...}
+# 117| getElement: [Pair] Pair
+# 117| getKey: [SymbolLiteral] :foo
+# 117| getValue: [IntegerLiteral] 1
+# 117| getElement: [Pair] Pair
+# 117| getKey: [SymbolLiteral] :bar
+# 117| getValue: [IntegerLiteral] 2
+# 117| getElement: [Pair] Pair
+# 117| getKey: [StringLiteral] "baz"
+# 117| getComponent: [StringTextComponent] baz
+# 117| getValue: [IntegerLiteral] 3
+# 118| getStmt: [HashLiteral] {...}
+# 118| getElement: [Pair] Pair
+# 118| getKey: [SymbolLiteral] :foo
+# 118| getValue: [IntegerLiteral] 7
+# 118| getElement: [HashSplatExpr] ** ...
+# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
+# 118| getReceiver: [Self, SelfVariableAccess] self
# 121| getStmt: [ParenthesizedExpr] ( ... )
# 121| getStmt: [RangeLiteral] _ .. _
# 121| getBegin: [IntegerLiteral] 1
+# 121| getEnd: [IntegerLiteral] 10
# 122| getStmt: [ParenthesizedExpr] ( ... )
-# 122| getStmt: [RangeLiteral] _ .. _
-# 122| getEnd: [IntegerLiteral] 1
+# 122| getStmt: [RangeLiteral] _ ... _
+# 122| getBegin: [IntegerLiteral] 1
+# 122| getEnd: [IntegerLiteral] 10
# 123| getStmt: [ParenthesizedExpr] ( ... )
-# 123| getStmt: [SubExpr] ... - ...
-# 123| getAnOperand/getLeftOperand/getReceiver: [RangeLiteral] _ .. _
-# 123| getBegin: [IntegerLiteral] 0
-# 123| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 126| getStmt: [SubshellLiteral] `ls -l`
-# 126| getComponent: [StringTextComponent] ls -l
-# 127| getStmt: [SubshellLiteral] `ls -l`
-# 127| getComponent: [StringTextComponent] ls -l
-# 128| getStmt: [SubshellLiteral] `du -d #{...}`
-# 128| getComponent: [StringTextComponent] du -d
-# 128| getComponent: [StringInterpolationComponent] #{...}
-# 128| getStmt: [AddExpr] ... + ...
-# 128| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 128| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 129| getStmt: [SubshellLiteral] `du -d #{...}`
-# 129| getComponent: [StringTextComponent] du -d
-# 129| getComponent: [StringInterpolationComponent] #{...}
-# 129| getStmt: [SubExpr] ... - ...
-# 129| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 5
-# 129| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
-# 132| getStmt: [RegExpLiteral] //
-# 133| getStmt: [RegExpLiteral] /foo/
-# 133| getParsed: [RegExpSequence] foo
-# 133| 0: [RegExpConstant, RegExpNormalChar] f
-# 133| 1: [RegExpConstant, RegExpNormalChar] o
-# 133| 2: [RegExpConstant, RegExpNormalChar] o
-# 133| getComponent: [StringTextComponent] foo
-# 134| getStmt: [RegExpLiteral] /foo/
-# 134| getParsed: [RegExpSequence] foo
-# 134| 0: [RegExpConstant, RegExpNormalChar] f
-# 134| 1: [RegExpConstant, RegExpNormalChar] o
-# 134| 2: [RegExpConstant, RegExpNormalChar] o
-# 134| getComponent: [StringTextComponent] foo
-# 135| getStmt: [RegExpLiteral] /foo+\sbar\S/
-# 135| getParsed: [RegExpSequence] foo+\sbar\S
-# 135| 0: [RegExpConstant, RegExpNormalChar] f
-# 135| 1: [RegExpConstant, RegExpNormalChar] o
-# 135| 2: [RegExpPlus] o+
-# 135| 0: [RegExpConstant, RegExpNormalChar] o
-# 135| 3: [RegExpCharacterClassEscape] \s
-# 135| 4: [RegExpConstant, RegExpNormalChar] b
-# 135| 5: [RegExpConstant, RegExpNormalChar] a
-# 135| 6: [RegExpConstant, RegExpNormalChar] r
-# 135| 7: [RegExpCharacterClassEscape] \S
-# 135| getComponent: [StringTextComponent] foo+
-# 135| getComponent: [StringEscapeSequenceComponent] \s
-# 135| getComponent: [StringTextComponent] bar
-# 135| getComponent: [StringEscapeSequenceComponent] \S
-# 136| getStmt: [RegExpLiteral] /foo#{...}bar/
-# 136| getComponent: [StringTextComponent] foo
-# 136| getComponent: [StringInterpolationComponent] #{...}
-# 136| getStmt: [AddExpr] ... + ...
-# 136| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 136| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 136| getComponent: [StringTextComponent] bar
+# 123| getStmt: [RangeLiteral] _ .. _
+# 123| getBegin: [IntegerLiteral] 1
+# 123| getEnd: [IntegerLiteral] 0
+# 124| getStmt: [ParenthesizedExpr] ( ... )
+# 124| getStmt: [RangeLiteral] _ .. _
+# 124| getBegin: [MethodCall] call to start
+# 124| getReceiver: [Self, SelfVariableAccess] self
+# 124| getEnd: [AddExpr] ... + ...
+# 124| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 124| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 3
+# 125| getStmt: [ParenthesizedExpr] ( ... )
+# 125| getStmt: [RangeLiteral] _ .. _
+# 125| getBegin: [IntegerLiteral] 1
+# 126| getStmt: [ParenthesizedExpr] ( ... )
+# 126| getStmt: [RangeLiteral] _ .. _
+# 126| getEnd: [IntegerLiteral] 1
+# 127| getStmt: [ParenthesizedExpr] ( ... )
+# 127| getStmt: [SubExpr] ... - ...
+# 127| getAnOperand/getLeftOperand/getReceiver: [RangeLiteral] _ .. _
+# 127| getBegin: [IntegerLiteral] 0
+# 127| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 130| getStmt: [SubshellLiteral] `ls -l`
+# 130| getComponent: [StringTextComponent] ls -l
+# 131| getStmt: [SubshellLiteral] `ls -l`
+# 131| getComponent: [StringTextComponent] ls -l
+# 132| getStmt: [SubshellLiteral] `du -d #{...}`
+# 132| getComponent: [StringTextComponent] du -d
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [AddExpr] ... + ...
+# 132| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 132| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 133| getStmt: [SubshellLiteral] `du -d #{...}`
+# 133| getComponent: [StringTextComponent] du -d
+# 133| getComponent: [StringInterpolationComponent] #{...}
+# 133| getStmt: [SubExpr] ... - ...
+# 133| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 5
+# 133| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 136| getStmt: [RegExpLiteral] //
# 137| getStmt: [RegExpLiteral] /foo/
# 137| getParsed: [RegExpSequence] foo
# 137| 0: [RegExpConstant, RegExpNormalChar] f
# 137| 1: [RegExpConstant, RegExpNormalChar] o
# 137| 2: [RegExpConstant, RegExpNormalChar] o
# 137| getComponent: [StringTextComponent] foo
-# 138| getStmt: [RegExpLiteral] //
-# 139| getStmt: [RegExpLiteral] /foo/
-# 139| getParsed: [RegExpSequence] foo
+# 138| getStmt: [RegExpLiteral] /foo/
+# 138| getParsed: [RegExpSequence] foo
+# 138| 0: [RegExpConstant, RegExpNormalChar] f
+# 138| 1: [RegExpConstant, RegExpNormalChar] o
+# 138| 2: [RegExpConstant, RegExpNormalChar] o
+# 138| getComponent: [StringTextComponent] foo
+# 139| getStmt: [RegExpLiteral] /foo+\sbar\S/
+# 139| getParsed: [RegExpSequence] foo+\sbar\S
# 139| 0: [RegExpConstant, RegExpNormalChar] f
# 139| 1: [RegExpConstant, RegExpNormalChar] o
-# 139| 2: [RegExpConstant, RegExpNormalChar] o
-# 139| getComponent: [StringTextComponent] foo
-# 140| getStmt: [RegExpLiteral] /foo/
-# 140| getParsed: [RegExpSequence] foo
-# 140| 0: [RegExpConstant, RegExpNormalChar] f
-# 140| 1: [RegExpConstant, RegExpNormalChar] o
-# 140| 2: [RegExpConstant, RegExpNormalChar] o
+# 139| 2: [RegExpPlus] o+
+# 139| 0: [RegExpConstant, RegExpNormalChar] o
+# 139| 3: [RegExpCharacterClassEscape] \s
+# 139| 4: [RegExpConstant, RegExpNormalChar] b
+# 139| 5: [RegExpConstant, RegExpNormalChar] a
+# 139| 6: [RegExpConstant, RegExpNormalChar] r
+# 139| 7: [RegExpCharacterClassEscape] \S
+# 139| getComponent: [StringTextComponent] foo+
+# 139| getComponent: [StringEscapeSequenceComponent] \s
+# 139| getComponent: [StringTextComponent] bar
+# 139| getComponent: [StringEscapeSequenceComponent] \S
+# 140| getStmt: [RegExpLiteral] /foo#{...}bar/
# 140| getComponent: [StringTextComponent] foo
-# 141| getStmt: [RegExpLiteral] /foo+\sbar\S/
-# 141| getParsed: [RegExpSequence] foo+\sbar\S
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [AddExpr] ... + ...
+# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 140| getComponent: [StringTextComponent] bar
+# 141| getStmt: [RegExpLiteral] /foo/
+# 141| getParsed: [RegExpSequence] foo
# 141| 0: [RegExpConstant, RegExpNormalChar] f
# 141| 1: [RegExpConstant, RegExpNormalChar] o
-# 141| 2: [RegExpPlus] o+
-# 141| 0: [RegExpConstant, RegExpNormalChar] o
-# 141| 3: [RegExpCharacterClassEscape] \s
-# 141| 4: [RegExpConstant, RegExpNormalChar] b
-# 141| 5: [RegExpConstant, RegExpNormalChar] a
-# 141| 6: [RegExpConstant, RegExpNormalChar] r
-# 141| 7: [RegExpCharacterClassEscape] \S
-# 141| getComponent: [StringTextComponent] foo+
-# 141| getComponent: [StringEscapeSequenceComponent] \s
-# 141| getComponent: [StringTextComponent] bar
-# 141| getComponent: [StringEscapeSequenceComponent] \S
-# 142| getStmt: [RegExpLiteral] /foo#{...}bar/
-# 142| getComponent: [StringTextComponent] foo
-# 142| getComponent: [StringInterpolationComponent] #{...}
-# 142| getStmt: [AddExpr] ... + ...
-# 142| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 142| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 142| getComponent: [StringTextComponent] bar
+# 141| 2: [RegExpConstant, RegExpNormalChar] o
+# 141| getComponent: [StringTextComponent] foo
+# 142| getStmt: [RegExpLiteral] //
# 143| getStmt: [RegExpLiteral] /foo/
# 143| getParsed: [RegExpSequence] foo
# 143| 0: [RegExpConstant, RegExpNormalChar] f
# 143| 1: [RegExpConstant, RegExpNormalChar] o
# 143| 2: [RegExpConstant, RegExpNormalChar] o
# 143| getComponent: [StringTextComponent] foo
-# 146| getStmt: [StringLiteral] "abcdefghijklmnopqrstuvwxyzabcdef"
-# 146| getComponent: [StringTextComponent] abcdefghijklmnopqrstuvwxyzabcdef
-# 147| getStmt: [StringLiteral] "foobarfoobarfoobarfoobarfooba..."
-# 147| getComponent: [StringTextComponent] foobarfoobarfoobarfoobarfoobarfoo
-# 148| getStmt: [StringLiteral] "foobar\\foobar\\foobar\\fooba..."
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 151| getStmt: [MethodCall] call to run_sql
-# 151| getReceiver: [Self, SelfVariableAccess] self
-# 151| getArgument: [HereDoc] < |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:69:1:69:2 | ?x | CharacterLiteral | ?x |
-| literals.rb:70:1:70:3 | ?\\n | CharacterLiteral | ?\\n |
-| literals.rb:71:1:71:3 | ?\\s | CharacterLiteral | ?\\s |
-| literals.rb:72:1:72:3 | ?\\\\ | CharacterLiteral | ?\\\\ |
-| literals.rb:73:1:73:7 | ?\\u{58} | CharacterLiteral | ?\\u{58} |
-| literals.rb:74:1:74:5 | ?\\C-a | CharacterLiteral | ?\\C-a |
-| literals.rb:75:1:75:5 | ?\\M-a | CharacterLiteral | ?\\M-a |
-| literals.rb:76:1:76:8 | ?\\M-\\C-a | CharacterLiteral | ?\\M-\\C-a |
-| literals.rb:77:1:77:8 | ?\\C-\\M-a | CharacterLiteral | ?\\C-\\M-a |
-| literals.rb:80:1:80:3 | :"" | SymbolLiteral | |
-| literals.rb:81:1:81:6 | :hello | SymbolLiteral | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | SymbolLiteral | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | SymbolLiteral | bar baz |
-| literals.rb:84:1:84:14 | {...} | HashLiteral | |
-| literals.rb:84:3:84:5 | :foo | SymbolLiteral | foo |
-| literals.rb:84:8:84:12 | "bar" | StringLiteral | bar |
-| literals.rb:85:1:85:10 | :"wibble" | SymbolLiteral | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
-| literals.rb:92:1:92:2 | [...] | ArrayLiteral | |
-| literals.rb:93:1:93:9 | [...] | ArrayLiteral | |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:1:94:14 | [...] | ArrayLiteral | |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:1:95:11 | [...] | ArrayLiteral | |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:5:95:10 | [...] | ArrayLiteral | |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:98:1:98:4 | %w(...) | ArrayLiteral | |
-| literals.rb:99:1:99:15 | %w(...) | ArrayLiteral | |
-| literals.rb:99:4:99:6 | "foo" | StringLiteral | foo |
-| literals.rb:99:8:99:10 | "bar" | StringLiteral | bar |
-| literals.rb:99:12:99:14 | "baz" | StringLiteral | baz |
-| literals.rb:100:1:100:15 | %w(...) | ArrayLiteral | |
-| literals.rb:100:4:100:6 | "foo" | StringLiteral | foo |
-| literals.rb:100:8:100:10 | "bar" | StringLiteral | bar |
-| literals.rb:100:12:100:14 | "baz" | StringLiteral | baz |
-| literals.rb:101:1:101:21 | %w(...) | ArrayLiteral | |
-| literals.rb:101:4:101:6 | "foo" | StringLiteral | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:18:101:20 | "baz" | StringLiteral | baz |
-| literals.rb:102:1:102:21 | %w(...) | ArrayLiteral | |
-| literals.rb:102:4:102:6 | "foo" | StringLiteral | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | StringLiteral | baz |
-| literals.rb:105:1:105:4 | %i(...) | ArrayLiteral | |
-| literals.rb:106:1:106:15 | %i(...) | ArrayLiteral | |
-| literals.rb:106:4:106:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:106:8:106:10 | :"bar" | SymbolLiteral | bar |
-| literals.rb:106:12:106:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:107:1:107:15 | %i(...) | ArrayLiteral | |
-| literals.rb:107:4:107:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:107:8:107:10 | :"bar" | SymbolLiteral | bar |
-| literals.rb:107:12:107:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:108:1:108:25 | %i(...) | ArrayLiteral | |
-| literals.rb:108:4:108:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:108:22:108:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:109:1:109:25 | %i(...) | ArrayLiteral | |
-| literals.rb:109:4:109:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | SymbolLiteral | 2 |
-| literals.rb:109:16:109:16 | :"+" | SymbolLiteral | + |
-| literals.rb:109:18:109:18 | :"4" | SymbolLiteral | 4 |
-| literals.rb:109:20:109:20 | :"}" | SymbolLiteral | } |
-| literals.rb:109:22:109:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:112:1:112:2 | {...} | HashLiteral | |
-| literals.rb:113:1:113:33 | {...} | HashLiteral | |
-| literals.rb:113:3:113:5 | :foo | SymbolLiteral | foo |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:11:113:14 | :bar | SymbolLiteral | bar |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:22:113:26 | "baz" | StringLiteral | baz |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:1:114:17 | {...} | HashLiteral | |
-| literals.rb:114:3:114:5 | :foo | SymbolLiteral | foo |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:2:117:6 | _ .. _ | RangeLiteral | |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:2:118:7 | _ ... _ | RangeLiteral | |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:2:119:7 | _ .. _ | RangeLiteral | |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:2:120:11 | _ .. _ | RangeLiteral | |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:73:1:73:2 | ?x | CharacterLiteral | ?x |
+| literals.rb:74:1:74:3 | ?\\n | CharacterLiteral | ?\\n |
+| literals.rb:75:1:75:3 | ?\\s | CharacterLiteral | ?\\s |
+| literals.rb:76:1:76:3 | ?\\\\ | CharacterLiteral | ?\\\\ |
+| literals.rb:77:1:77:7 | ?\\u{58} | CharacterLiteral | ?\\u{58} |
+| literals.rb:78:1:78:5 | ?\\C-a | CharacterLiteral | ?\\C-a |
+| literals.rb:79:1:79:5 | ?\\M-a | CharacterLiteral | ?\\M-a |
+| literals.rb:80:1:80:8 | ?\\M-\\C-a | CharacterLiteral | ?\\M-\\C-a |
+| literals.rb:81:1:81:8 | ?\\C-\\M-a | CharacterLiteral | ?\\C-\\M-a |
+| literals.rb:84:1:84:3 | :"" | SymbolLiteral | |
+| literals.rb:85:1:85:6 | :hello | SymbolLiteral | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | SymbolLiteral | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | SymbolLiteral | bar baz |
+| literals.rb:88:1:88:14 | {...} | HashLiteral | |
+| literals.rb:88:3:88:5 | :foo | SymbolLiteral | foo |
+| literals.rb:88:8:88:12 | "bar" | StringLiteral | bar |
+| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
+| literals.rb:96:1:96:2 | [...] | ArrayLiteral | |
+| literals.rb:97:1:97:9 | [...] | ArrayLiteral | |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:1:98:14 | [...] | ArrayLiteral | |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:1:99:11 | [...] | ArrayLiteral | |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:5:99:10 | [...] | ArrayLiteral | |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:102:1:102:4 | %w(...) | ArrayLiteral | |
+| literals.rb:103:1:103:15 | %w(...) | ArrayLiteral | |
+| literals.rb:103:4:103:6 | "foo" | StringLiteral | foo |
+| literals.rb:103:8:103:10 | "bar" | StringLiteral | bar |
+| literals.rb:103:12:103:14 | "baz" | StringLiteral | baz |
+| literals.rb:104:1:104:15 | %w(...) | ArrayLiteral | |
+| literals.rb:104:4:104:6 | "foo" | StringLiteral | foo |
+| literals.rb:104:8:104:10 | "bar" | StringLiteral | bar |
+| literals.rb:104:12:104:14 | "baz" | StringLiteral | baz |
+| literals.rb:105:1:105:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:4:105:6 | "foo" | StringLiteral | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:18:105:20 | "baz" | StringLiteral | baz |
+| literals.rb:106:1:106:21 | %w(...) | ArrayLiteral | |
+| literals.rb:106:4:106:6 | "foo" | StringLiteral | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | StringLiteral | baz |
+| literals.rb:109:1:109:4 | %i(...) | ArrayLiteral | |
+| literals.rb:110:1:110:15 | %i(...) | ArrayLiteral | |
+| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:110:8:110:10 | :"bar" | SymbolLiteral | bar |
+| literals.rb:110:12:110:14 | :"baz" | SymbolLiteral | baz |
+| literals.rb:111:1:111:15 | %i(...) | ArrayLiteral | |
+| literals.rb:111:4:111:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:111:8:111:10 | :"bar" | SymbolLiteral | bar |
+| literals.rb:111:12:111:14 | :"baz" | SymbolLiteral | baz |
+| literals.rb:112:1:112:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:1:113:25 | %i(...) | ArrayLiteral | |
+| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 2 |
+| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | + |
+| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 4 |
+| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | } |
+| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:116:1:116:2 | {...} | HashLiteral | |
+| literals.rb:117:1:117:33 | {...} | HashLiteral | |
+| literals.rb:117:3:117:5 | :foo | SymbolLiteral | foo |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:11:117:14 | :bar | SymbolLiteral | bar |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:22:117:26 | "baz" | StringLiteral | baz |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:1:118:17 | {...} | HashLiteral | |
+| literals.rb:118:3:118:5 | :foo | SymbolLiteral | foo |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:121:2:121:4 | _ .. _ | RangeLiteral | |
-| literals.rb:122:2:122:4 | _ .. _ | RangeLiteral | |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:2:123:4 | _ .. _ | RangeLiteral | |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:126:1:126:7 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:132:1:132:2 | // | RegExpLiteral | |
-| literals.rb:133:1:133:5 | /foo/ | RegExpLiteral | foo |
-| literals.rb:134:1:134:6 | /foo/ | RegExpLiteral | foo |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:137:1:137:8 | /foo/ | RegExpLiteral | foo |
-| literals.rb:138:1:138:4 | // | RegExpLiteral | |
-| literals.rb:139:1:139:7 | /foo/ | RegExpLiteral | foo |
-| literals.rb:140:1:140:8 | /foo/ | RegExpLiteral | foo |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
-| literals.rb:143:1:143:10 | /foo/ | RegExpLiteral | foo |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
-| literals.rb:151:9:151:13 | < |
-| literals.rb:158:11:158:16 | <<-BLA | HereDoc | \nsome text\\nand some more\n |
-| literals.rb:163:9:163:19 | <<~SQUIGGLY | HereDoc | \n indented stuff\n |
-| literals.rb:167:9:167:15 | <<"DOC" | HereDoc | |
-| literals.rb:172:9:172:15 | <<'DOC' | HereDoc | |
-| literals.rb:176:10:176:19 | <<`SCRIPT` | HereDoc | \n cat file.txt\n |
+| literals.rb:121:2:121:6 | _ .. _ | RangeLiteral | |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:2:122:7 | _ ... _ | RangeLiteral | |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:2:123:7 | _ .. _ | RangeLiteral | |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:2:124:11 | _ .. _ | RangeLiteral | |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:125:2:125:4 | _ .. _ | RangeLiteral | |
+| literals.rb:126:2:126:4 | _ .. _ | RangeLiteral | |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:2:127:4 | _ .. _ | RangeLiteral | |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:136:1:136:2 | // | RegExpLiteral | |
+| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | foo |
+| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | foo |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:142:1:142:4 | // | RegExpLiteral | |
+| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
+| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:155:9:155:13 | < |
+| literals.rb:162:11:162:16 | <<-BLA | HereDoc | \nsome text\\nand some more\n |
+| literals.rb:167:9:167:19 | <<~SQUIGGLY | HereDoc | \n indented stuff\n |
+| literals.rb:171:9:171:15 | <<"DOC" | HereDoc | |
+| literals.rb:176:9:176:15 | <<'DOC' | HereDoc | |
+| literals.rb:180:10:180:19 | <<`SCRIPT` | HereDoc | \n cat file.txt\n |
stringlikeLiterals
| literals.rb:46:1:46:2 | "" | |
| literals.rb:47:1:47:2 | "" | |
@@ -234,75 +234,75 @@ stringlikeLiterals
| literals.rb:65:1:65:35 | "foo #{...} qux" | |
| literals.rb:65:9:65:28 | "bar #{...} baz" | |
| literals.rb:66:1:66:22 | "foo #{...}" | |
-| literals.rb:80:1:80:3 | :"" | |
-| literals.rb:81:1:81:6 | :hello | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | bar baz |
-| literals.rb:84:3:84:5 | :foo | foo |
-| literals.rb:84:8:84:12 | "bar" | bar |
-| literals.rb:85:1:85:10 | :"wibble" | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
-| literals.rb:99:4:99:6 | "foo" | foo |
-| literals.rb:99:8:99:10 | "bar" | bar |
-| literals.rb:99:12:99:14 | "baz" | baz |
-| literals.rb:100:4:100:6 | "foo" | foo |
-| literals.rb:100:8:100:10 | "bar" | bar |
-| literals.rb:100:12:100:14 | "baz" | baz |
-| literals.rb:101:4:101:6 | "foo" | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | |
-| literals.rb:101:18:101:20 | "baz" | baz |
-| literals.rb:102:4:102:6 | "foo" | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | baz |
-| literals.rb:106:4:106:6 | :"foo" | foo |
-| literals.rb:106:8:106:10 | :"bar" | bar |
-| literals.rb:106:12:106:14 | :"baz" | baz |
-| literals.rb:107:4:107:6 | :"foo" | foo |
-| literals.rb:107:8:107:10 | :"bar" | bar |
-| literals.rb:107:12:107:14 | :"baz" | baz |
-| literals.rb:108:4:108:6 | :"foo" | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | |
-| literals.rb:108:22:108:24 | :"baz" | baz |
-| literals.rb:109:4:109:6 | :"foo" | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | 2 |
-| literals.rb:109:16:109:16 | :"+" | + |
-| literals.rb:109:18:109:18 | :"4" | 4 |
-| literals.rb:109:20:109:20 | :"}" | } |
-| literals.rb:109:22:109:24 | :"baz" | baz |
-| literals.rb:113:3:113:5 | :foo | foo |
-| literals.rb:113:11:113:14 | :bar | bar |
-| literals.rb:113:22:113:26 | "baz" | baz |
-| literals.rb:114:3:114:5 | :foo | foo |
-| literals.rb:126:1:126:7 | `ls -l` | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | |
-| literals.rb:129:1:129:20 | `du -d #{...}` | |
-| literals.rb:132:1:132:2 | // | |
-| literals.rb:133:1:133:5 | /foo/ | foo |
-| literals.rb:134:1:134:6 | /foo/ | foo |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | |
-| literals.rb:137:1:137:8 | /foo/ | foo |
-| literals.rb:138:1:138:4 | // | |
-| literals.rb:139:1:139:7 | /foo/ | foo |
-| literals.rb:140:1:140:8 | /foo/ | foo |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | |
-| literals.rb:143:1:143:10 | /foo/ | foo |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
-| literals.rb:151:9:151:13 | < |
-| literals.rb:158:11:158:16 | <<-BLA | \nsome text\\nand some more\n |
-| literals.rb:163:9:163:19 | <<~SQUIGGLY | \n indented stuff\n |
-| literals.rb:167:9:167:15 | <<"DOC" | |
-| literals.rb:172:9:172:15 | <<'DOC' | |
-| literals.rb:176:10:176:19 | <<`SCRIPT` | \n cat file.txt\n |
+| literals.rb:84:1:84:3 | :"" | |
+| literals.rb:85:1:85:6 | :hello | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | bar baz |
+| literals.rb:88:3:88:5 | :foo | foo |
+| literals.rb:88:8:88:12 | "bar" | bar |
+| literals.rb:89:1:89:10 | :"wibble" | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
+| literals.rb:103:4:103:6 | "foo" | foo |
+| literals.rb:103:8:103:10 | "bar" | bar |
+| literals.rb:103:12:103:14 | "baz" | baz |
+| literals.rb:104:4:104:6 | "foo" | foo |
+| literals.rb:104:8:104:10 | "bar" | bar |
+| literals.rb:104:12:104:14 | "baz" | baz |
+| literals.rb:105:4:105:6 | "foo" | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | |
+| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:106:4:106:6 | "foo" | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:110:4:110:6 | :"foo" | foo |
+| literals.rb:110:8:110:10 | :"bar" | bar |
+| literals.rb:110:12:110:14 | :"baz" | baz |
+| literals.rb:111:4:111:6 | :"foo" | foo |
+| literals.rb:111:8:111:10 | :"bar" | bar |
+| literals.rb:111:12:111:14 | :"baz" | baz |
+| literals.rb:112:4:112:6 | :"foo" | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | |
+| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:113:4:113:6 | :"foo" | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | 2 |
+| literals.rb:113:16:113:16 | :"+" | + |
+| literals.rb:113:18:113:18 | :"4" | 4 |
+| literals.rb:113:20:113:20 | :"}" | } |
+| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:117:3:117:5 | :foo | foo |
+| literals.rb:117:11:117:14 | :bar | bar |
+| literals.rb:117:22:117:26 | "baz" | baz |
+| literals.rb:118:3:118:5 | :foo | foo |
+| literals.rb:130:1:130:7 | `ls -l` | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:136:1:136:2 | // | |
+| literals.rb:137:1:137:5 | /foo/ | foo |
+| literals.rb:138:1:138:6 | /foo/ | foo |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | |
+| literals.rb:141:1:141:8 | /foo/ | foo |
+| literals.rb:142:1:142:4 | // | |
+| literals.rb:143:1:143:7 | /foo/ | foo |
+| literals.rb:144:1:144:8 | /foo/ | foo |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | |
+| literals.rb:147:1:147:10 | /foo/ | foo |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:155:9:155:13 | < |
+| literals.rb:162:11:162:16 | <<-BLA | \nsome text\\nand some more\n |
+| literals.rb:167:9:167:19 | <<~SQUIGGLY | \n indented stuff\n |
+| literals.rb:171:9:171:15 | <<"DOC" | |
+| literals.rb:176:9:176:15 | <<'DOC' | |
+| literals.rb:180:10:180:19 | <<`SCRIPT` | \n cat file.txt\n |
stringLiterals
| literals.rb:46:1:46:2 | "" | |
| literals.rb:47:1:47:2 | "" | |
@@ -332,71 +332,71 @@ stringLiterals
| literals.rb:65:1:65:35 | "foo #{...} qux" | |
| literals.rb:65:9:65:28 | "bar #{...} baz" | |
| literals.rb:66:1:66:22 | "foo #{...}" | |
-| literals.rb:84:8:84:12 | "bar" | bar |
-| literals.rb:99:4:99:6 | "foo" | foo |
-| literals.rb:99:8:99:10 | "bar" | bar |
-| literals.rb:99:12:99:14 | "baz" | baz |
-| literals.rb:100:4:100:6 | "foo" | foo |
-| literals.rb:100:8:100:10 | "bar" | bar |
-| literals.rb:100:12:100:14 | "baz" | baz |
-| literals.rb:101:4:101:6 | "foo" | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | |
-| literals.rb:101:18:101:20 | "baz" | baz |
-| literals.rb:102:4:102:6 | "foo" | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | baz |
-| literals.rb:113:22:113:26 | "baz" | baz |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:88:8:88:12 | "bar" | bar |
+| literals.rb:103:4:103:6 | "foo" | foo |
+| literals.rb:103:8:103:10 | "bar" | bar |
+| literals.rb:103:12:103:14 | "baz" | baz |
+| literals.rb:104:4:104:6 | "foo" | foo |
+| literals.rb:104:8:104:10 | "bar" | bar |
+| literals.rb:104:12:104:14 | "baz" | baz |
+| literals.rb:105:4:105:6 | "foo" | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | |
+| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:106:4:106:6 | "foo" | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:117:22:117:26 | "baz" | baz |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
regExpLiterals
-| literals.rb:132:1:132:2 | // | | |
-| literals.rb:133:1:133:5 | /foo/ | foo | |
-| literals.rb:134:1:134:6 | /foo/ | foo | i |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | | |
-| literals.rb:137:1:137:8 | /foo/ | foo | oxm |
-| literals.rb:138:1:138:4 | // | | |
-| literals.rb:139:1:139:7 | /foo/ | foo | |
-| literals.rb:140:1:140:8 | /foo/ | foo | i |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | | |
-| literals.rb:143:1:143:10 | /foo/ | foo | mxo |
+| literals.rb:136:1:136:2 | // | | |
+| literals.rb:137:1:137:5 | /foo/ | foo | |
+| literals.rb:138:1:138:6 | /foo/ | foo | i |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | | |
+| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
+| literals.rb:142:1:142:4 | // | | |
+| literals.rb:143:1:143:7 | /foo/ | foo | |
+| literals.rb:144:1:144:8 | /foo/ | foo | i |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | | |
+| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
symbolLiterals
-| literals.rb:80:1:80:3 | :"" | |
-| literals.rb:81:1:81:6 | :hello | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | bar baz |
-| literals.rb:84:3:84:5 | :foo | foo |
-| literals.rb:85:1:85:10 | :"wibble" | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
-| literals.rb:106:4:106:6 | :"foo" | foo |
-| literals.rb:106:8:106:10 | :"bar" | bar |
-| literals.rb:106:12:106:14 | :"baz" | baz |
-| literals.rb:107:4:107:6 | :"foo" | foo |
-| literals.rb:107:8:107:10 | :"bar" | bar |
-| literals.rb:107:12:107:14 | :"baz" | baz |
-| literals.rb:108:4:108:6 | :"foo" | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | |
-| literals.rb:108:22:108:24 | :"baz" | baz |
-| literals.rb:109:4:109:6 | :"foo" | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | 2 |
-| literals.rb:109:16:109:16 | :"+" | + |
-| literals.rb:109:18:109:18 | :"4" | 4 |
-| literals.rb:109:20:109:20 | :"}" | } |
-| literals.rb:109:22:109:24 | :"baz" | baz |
-| literals.rb:113:3:113:5 | :foo | foo |
-| literals.rb:113:11:113:14 | :bar | bar |
-| literals.rb:114:3:114:5 | :foo | foo |
+| literals.rb:84:1:84:3 | :"" | |
+| literals.rb:85:1:85:6 | :hello | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | bar baz |
+| literals.rb:88:3:88:5 | :foo | foo |
+| literals.rb:89:1:89:10 | :"wibble" | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
+| literals.rb:110:4:110:6 | :"foo" | foo |
+| literals.rb:110:8:110:10 | :"bar" | bar |
+| literals.rb:110:12:110:14 | :"baz" | baz |
+| literals.rb:111:4:111:6 | :"foo" | foo |
+| literals.rb:111:8:111:10 | :"bar" | bar |
+| literals.rb:111:12:111:14 | :"baz" | baz |
+| literals.rb:112:4:112:6 | :"foo" | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | |
+| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:113:4:113:6 | :"foo" | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | 2 |
+| literals.rb:113:16:113:16 | :"+" | + |
+| literals.rb:113:18:113:18 | :"4" | 4 |
+| literals.rb:113:20:113:20 | :"}" | } |
+| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:117:3:117:5 | :foo | foo |
+| literals.rb:117:11:117:14 | :bar | bar |
+| literals.rb:118:3:118:5 | :foo | foo |
subshellLiterals
-| literals.rb:126:1:126:7 | `ls -l` | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | |
-| literals.rb:129:1:129:20 | `du -d #{...}` | |
+| literals.rb:130:1:130:7 | `ls -l` | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | |
stringComponents
| literals.rb:48:1:48:7 | "hello" | StringLiteral | 0 | literals.rb:48:2:48:6 | hello | StringTextComponent |
| literals.rb:49:1:49:9 | "goodbye" | StringLiteral | 0 | literals.rb:49:2:49:8 | goodbye | StringTextComponent |
@@ -436,98 +436,98 @@ stringComponents
| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | 2 | literals.rb:65:24:65:27 | baz | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 0 | literals.rb:66:2:66:5 | foo | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 1 | literals.rb:66:6:66:21 | #{...} | StringInterpolationComponent |
-| literals.rb:82:1:82:10 | :"foo bar" | SymbolLiteral | 0 | literals.rb:82:3:82:9 | foo bar | StringTextComponent |
-| literals.rb:83:1:83:10 | :"bar baz" | SymbolLiteral | 0 | literals.rb:83:3:83:9 | bar baz | StringTextComponent |
-| literals.rb:84:8:84:12 | "bar" | StringLiteral | 0 | literals.rb:84:9:84:11 | bar | StringTextComponent |
-| literals.rb:85:1:85:10 | :"wibble" | SymbolLiteral | 0 | literals.rb:85:4:85:9 | wibble | StringTextComponent |
-| literals.rb:86:1:86:17 | :"wibble wobble" | SymbolLiteral | 0 | literals.rb:86:4:86:16 | wibble wobble | StringTextComponent |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | 0 | literals.rb:87:3:87:6 | foo_ | StringTextComponent |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | 1 | literals.rb:87:7:87:15 | #{...} | StringInterpolationComponent |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | 0 | literals.rb:88:3:88:16 | foo_#{ 1 + 1 } | StringTextComponent |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | 0 | literals.rb:89:4:89:17 | foo_#{ 3 - 2 } | StringTextComponent |
-| literals.rb:99:4:99:6 | "foo" | StringLiteral | 0 | literals.rb:99:4:99:6 | foo | StringTextComponent |
-| literals.rb:99:8:99:10 | "bar" | StringLiteral | 0 | literals.rb:99:8:99:10 | bar | StringTextComponent |
-| literals.rb:99:12:99:14 | "baz" | StringLiteral | 0 | literals.rb:99:12:99:14 | baz | StringTextComponent |
-| literals.rb:100:4:100:6 | "foo" | StringLiteral | 0 | literals.rb:100:4:100:6 | foo | StringTextComponent |
-| literals.rb:100:8:100:10 | "bar" | StringLiteral | 0 | literals.rb:100:8:100:10 | bar | StringTextComponent |
-| literals.rb:100:12:100:14 | "baz" | StringLiteral | 0 | literals.rb:100:12:100:14 | baz | StringTextComponent |
-| literals.rb:101:4:101:6 | "foo" | StringLiteral | 0 | literals.rb:101:4:101:6 | foo | StringTextComponent |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | 0 | literals.rb:101:8:101:10 | bar | StringTextComponent |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | 1 | literals.rb:101:11:101:16 | #{...} | StringInterpolationComponent |
-| literals.rb:101:18:101:20 | "baz" | StringLiteral | 0 | literals.rb:101:18:101:20 | baz | StringTextComponent |
-| literals.rb:102:4:102:6 | "foo" | StringLiteral | 0 | literals.rb:102:4:102:6 | foo | StringTextComponent |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral | 0 | literals.rb:102:8:102:16 | bar#{1+1} | StringTextComponent |
-| literals.rb:102:18:102:20 | "baz" | StringLiteral | 0 | literals.rb:102:18:102:20 | baz | StringTextComponent |
-| literals.rb:106:4:106:6 | :"foo" | SymbolLiteral | 0 | literals.rb:106:4:106:6 | foo | StringTextComponent |
-| literals.rb:106:8:106:10 | :"bar" | SymbolLiteral | 0 | literals.rb:106:8:106:10 | bar | StringTextComponent |
-| literals.rb:106:12:106:14 | :"baz" | SymbolLiteral | 0 | literals.rb:106:12:106:14 | baz | StringTextComponent |
-| literals.rb:107:4:107:6 | :"foo" | SymbolLiteral | 0 | literals.rb:107:4:107:6 | foo | StringTextComponent |
-| literals.rb:107:8:107:10 | :"bar" | SymbolLiteral | 0 | literals.rb:107:8:107:10 | bar | StringTextComponent |
-| literals.rb:107:12:107:14 | :"baz" | SymbolLiteral | 0 | literals.rb:107:12:107:14 | baz | StringTextComponent |
-| literals.rb:108:4:108:6 | :"foo" | SymbolLiteral | 0 | literals.rb:108:4:108:6 | foo | StringTextComponent |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | 0 | literals.rb:108:8:108:10 | bar | StringTextComponent |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | 1 | literals.rb:108:11:108:20 | #{...} | StringInterpolationComponent |
-| literals.rb:108:22:108:24 | :"baz" | SymbolLiteral | 0 | literals.rb:108:22:108:24 | baz | StringTextComponent |
-| literals.rb:109:4:109:6 | :"foo" | SymbolLiteral | 0 | literals.rb:109:4:109:6 | foo | StringTextComponent |
-| literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral | 0 | literals.rb:109:8:109:12 | bar#{ | StringTextComponent |
-| literals.rb:109:14:109:14 | :"2" | SymbolLiteral | 0 | literals.rb:109:14:109:14 | 2 | StringTextComponent |
-| literals.rb:109:16:109:16 | :"+" | SymbolLiteral | 0 | literals.rb:109:16:109:16 | + | StringTextComponent |
-| literals.rb:109:18:109:18 | :"4" | SymbolLiteral | 0 | literals.rb:109:18:109:18 | 4 | StringTextComponent |
-| literals.rb:109:20:109:20 | :"}" | SymbolLiteral | 0 | literals.rb:109:20:109:20 | } | StringTextComponent |
-| literals.rb:109:22:109:24 | :"baz" | SymbolLiteral | 0 | literals.rb:109:22:109:24 | baz | StringTextComponent |
-| literals.rb:113:22:113:26 | "baz" | StringLiteral | 0 | literals.rb:113:23:113:25 | baz | StringTextComponent |
-| literals.rb:126:1:126:7 | `ls -l` | SubshellLiteral | 0 | literals.rb:126:2:126:6 | ls -l | StringTextComponent |
-| literals.rb:127:1:127:9 | `ls -l` | SubshellLiteral | 0 | literals.rb:127:4:127:8 | ls -l | StringTextComponent |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:128:2:128:7 | du -d | StringTextComponent |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:128:8:128:17 | #{...} | StringInterpolationComponent |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:129:4:129:9 | du -d | StringTextComponent |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:129:10:129:19 | #{...} | StringInterpolationComponent |
-| literals.rb:133:1:133:5 | /foo/ | RegExpLiteral | 0 | literals.rb:133:2:133:4 | foo | StringTextComponent |
-| literals.rb:134:1:134:6 | /foo/ | RegExpLiteral | 0 | literals.rb:134:2:134:4 | foo | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:135:2:135:5 | foo+ | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:135:6:135:7 | \\s | StringEscapeSequenceComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:135:8:135:10 | bar | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:135:11:135:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:136:2:136:4 | foo | StringTextComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:136:5:136:14 | #{...} | StringInterpolationComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:136:15:136:17 | bar | StringTextComponent |
-| literals.rb:137:1:137:8 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
-| literals.rb:139:1:139:7 | /foo/ | RegExpLiteral | 0 | literals.rb:139:4:139:6 | foo | StringTextComponent |
-| literals.rb:140:1:140:8 | /foo/ | RegExpLiteral | 0 | literals.rb:140:4:140:6 | foo | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:141:4:141:7 | foo+ | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:141:8:141:9 | \\s | StringEscapeSequenceComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:141:10:141:12 | bar | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:141:13:141:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:142:4:142:6 | foo | StringTextComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:142:7:142:16 | #{...} | StringInterpolationComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:142:17:142:19 | bar | StringTextComponent |
-| literals.rb:143:1:143:10 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:146:2:146:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:147:2:147:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 0 | literals.rb:148:2:148:7 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 1 | literals.rb:148:8:148:9 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 2 | literals.rb:148:10:148:15 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 3 | literals.rb:148:16:148:17 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 4 | literals.rb:148:18:148:23 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 5 | literals.rb:148:24:148:25 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 6 | literals.rb:148:26:148:31 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 7 | literals.rb:148:32:148:33 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 8 | literals.rb:148:34:148:39 | foobar | StringTextComponent |
-| literals.rb:151:9:151:13 | < | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
| literals.rb:64:1:64:27 | "..." "..." | | 2 | literals.rb:64:23:64:27 | "baz" |
arrayLiterals
-| literals.rb:92:1:92:2 | [...] | 0 |
-| literals.rb:93:1:93:9 | [...] | 3 |
-| literals.rb:94:1:94:14 | [...] | 3 |
-| literals.rb:95:1:95:11 | [...] | 2 |
-| literals.rb:95:5:95:10 | [...] | 2 |
-| literals.rb:98:1:98:4 | %w(...) | 0 |
-| literals.rb:99:1:99:15 | %w(...) | 3 |
-| literals.rb:100:1:100:15 | %w(...) | 3 |
-| literals.rb:101:1:101:21 | %w(...) | 3 |
-| literals.rb:102:1:102:21 | %w(...) | 3 |
-| literals.rb:105:1:105:4 | %i(...) | 0 |
-| literals.rb:106:1:106:15 | %i(...) | 3 |
-| literals.rb:107:1:107:15 | %i(...) | 3 |
-| literals.rb:108:1:108:25 | %i(...) | 3 |
-| literals.rb:109:1:109:25 | %i(...) | 7 |
+| literals.rb:96:1:96:2 | [...] | 0 |
+| literals.rb:97:1:97:9 | [...] | 3 |
+| literals.rb:98:1:98:14 | [...] | 3 |
+| literals.rb:99:1:99:11 | [...] | 2 |
+| literals.rb:99:5:99:10 | [...] | 2 |
+| literals.rb:102:1:102:4 | %w(...) | 0 |
+| literals.rb:103:1:103:15 | %w(...) | 3 |
+| literals.rb:104:1:104:15 | %w(...) | 3 |
+| literals.rb:105:1:105:21 | %w(...) | 3 |
+| literals.rb:106:1:106:21 | %w(...) | 3 |
+| literals.rb:109:1:109:4 | %i(...) | 0 |
+| literals.rb:110:1:110:15 | %i(...) | 3 |
+| literals.rb:111:1:111:15 | %i(...) | 3 |
+| literals.rb:112:1:112:25 | %i(...) | 3 |
+| literals.rb:113:1:113:25 | %i(...) | 7 |
arrayLiteralElements
-| literals.rb:93:1:93:9 | [...] | 0 | literals.rb:93:2:93:2 | 1 | IntegerLiteral |
-| literals.rb:93:1:93:9 | [...] | 1 | literals.rb:93:5:93:5 | 2 | IntegerLiteral |
-| literals.rb:93:1:93:9 | [...] | 2 | literals.rb:93:8:93:8 | 3 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 0 | literals.rb:94:2:94:2 | 4 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 1 | literals.rb:94:5:94:5 | 5 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 2 | literals.rb:94:8:94:13 | ... / ... | DivExpr |
-| literals.rb:95:1:95:11 | [...] | 0 | literals.rb:95:2:95:2 | 7 | IntegerLiteral |
-| literals.rb:95:1:95:11 | [...] | 1 | literals.rb:95:5:95:10 | [...] | ArrayLiteral |
-| literals.rb:95:5:95:10 | [...] | 0 | literals.rb:95:6:95:6 | 8 | IntegerLiteral |
-| literals.rb:95:5:95:10 | [...] | 1 | literals.rb:95:9:95:9 | 9 | IntegerLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 0 | literals.rb:99:4:99:6 | "foo" | StringLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 1 | literals.rb:99:8:99:10 | "bar" | StringLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 2 | literals.rb:99:12:99:14 | "baz" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 0 | literals.rb:100:4:100:6 | "foo" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 1 | literals.rb:100:8:100:10 | "bar" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 2 | literals.rb:100:12:100:14 | "baz" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 0 | literals.rb:101:4:101:6 | "foo" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 1 | literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 2 | literals.rb:101:18:101:20 | "baz" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 0 | literals.rb:102:4:102:6 | "foo" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 1 | literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 2 | literals.rb:102:18:102:20 | "baz" | StringLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 0 | literals.rb:106:4:106:6 | :"foo" | SymbolLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 1 | literals.rb:106:8:106:10 | :"bar" | SymbolLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 2 | literals.rb:106:12:106:14 | :"baz" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 0 | literals.rb:107:4:107:6 | :"foo" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 1 | literals.rb:107:8:107:10 | :"bar" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 2 | literals.rb:107:12:107:14 | :"baz" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 0 | literals.rb:108:4:108:6 | :"foo" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 1 | literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 2 | literals.rb:108:22:108:24 | :"baz" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 0 | literals.rb:109:4:109:6 | :"foo" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 1 | literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 2 | literals.rb:109:14:109:14 | :"2" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 3 | literals.rb:109:16:109:16 | :"+" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 4 | literals.rb:109:18:109:18 | :"4" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 5 | literals.rb:109:20:109:20 | :"}" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 6 | literals.rb:109:22:109:24 | :"baz" | SymbolLiteral |
+| literals.rb:97:1:97:9 | [...] | 0 | literals.rb:97:2:97:2 | 1 | IntegerLiteral |
+| literals.rb:97:1:97:9 | [...] | 1 | literals.rb:97:5:97:5 | 2 | IntegerLiteral |
+| literals.rb:97:1:97:9 | [...] | 2 | literals.rb:97:8:97:8 | 3 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 0 | literals.rb:98:2:98:2 | 4 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 1 | literals.rb:98:5:98:5 | 5 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 2 | literals.rb:98:8:98:13 | ... / ... | DivExpr |
+| literals.rb:99:1:99:11 | [...] | 0 | literals.rb:99:2:99:2 | 7 | IntegerLiteral |
+| literals.rb:99:1:99:11 | [...] | 1 | literals.rb:99:5:99:10 | [...] | ArrayLiteral |
+| literals.rb:99:5:99:10 | [...] | 0 | literals.rb:99:6:99:6 | 8 | IntegerLiteral |
+| literals.rb:99:5:99:10 | [...] | 1 | literals.rb:99:9:99:9 | 9 | IntegerLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 0 | literals.rb:103:4:103:6 | "foo" | StringLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 1 | literals.rb:103:8:103:10 | "bar" | StringLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 2 | literals.rb:103:12:103:14 | "baz" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 0 | literals.rb:104:4:104:6 | "foo" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 1 | literals.rb:104:8:104:10 | "bar" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 2 | literals.rb:104:12:104:14 | "baz" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 2 | literals.rb:105:18:105:20 | "baz" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 2 | literals.rb:106:18:106:20 | "baz" | StringLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 0 | literals.rb:110:4:110:6 | :"foo" | SymbolLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 1 | literals.rb:110:8:110:10 | :"bar" | SymbolLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 2 | literals.rb:110:12:110:14 | :"baz" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 0 | literals.rb:111:4:111:6 | :"foo" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 1 | literals.rb:111:8:111:10 | :"bar" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 2 | literals.rb:111:12:111:14 | :"baz" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 2 | literals.rb:112:22:112:24 | :"baz" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 6 | literals.rb:113:22:113:24 | :"baz" | SymbolLiteral |
hashLiterals
-| literals.rb:84:1:84:14 | {...} | 1 |
-| literals.rb:112:1:112:2 | {...} | 0 |
-| literals.rb:113:1:113:33 | {...} | 3 |
-| literals.rb:114:1:114:17 | {...} | 2 |
+| literals.rb:88:1:88:14 | {...} | 1 |
+| literals.rb:116:1:116:2 | {...} | 0 |
+| literals.rb:117:1:117:33 | {...} | 3 |
+| literals.rb:118:1:118:17 | {...} | 2 |
hashLiteralElements
-| literals.rb:84:1:84:14 | {...} | 0 | literals.rb:84:3:84:12 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 0 | literals.rb:113:3:113:8 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 1 | literals.rb:113:11:113:19 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 2 | literals.rb:113:22:113:31 | Pair | Pair |
-| literals.rb:114:1:114:17 | {...} | 0 | literals.rb:114:3:114:8 | Pair | Pair |
-| literals.rb:114:1:114:17 | {...} | 1 | literals.rb:114:11:114:15 | ** ... | HashSplatExpr |
+| literals.rb:88:1:88:14 | {...} | 0 | literals.rb:88:3:88:12 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 0 | literals.rb:117:3:117:8 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 1 | literals.rb:117:11:117:19 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 2 | literals.rb:117:22:117:31 | Pair | Pair |
+| literals.rb:118:1:118:17 | {...} | 0 | literals.rb:118:3:118:8 | Pair | Pair |
+| literals.rb:118:1:118:17 | {...} | 1 | literals.rb:118:11:118:15 | ** ... | HashSplatExpr |
hashLiteralKeyValuePairs
-| literals.rb:84:1:84:14 | {...} | literals.rb:84:3:84:12 | Pair | literals.rb:84:3:84:5 | :foo | literals.rb:84:8:84:12 | "bar" |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:3:113:8 | Pair | literals.rb:113:3:113:5 | :foo | literals.rb:113:8:113:8 | 1 |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:11:113:19 | Pair | literals.rb:113:11:113:14 | :bar | literals.rb:113:19:113:19 | 2 |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:22:113:31 | Pair | literals.rb:113:22:113:26 | "baz" | literals.rb:113:31:113:31 | 3 |
-| literals.rb:114:1:114:17 | {...} | literals.rb:114:3:114:8 | Pair | literals.rb:114:3:114:5 | :foo | literals.rb:114:8:114:8 | 7 |
+| literals.rb:88:1:88:14 | {...} | literals.rb:88:3:88:12 | Pair | literals.rb:88:3:88:5 | :foo | literals.rb:88:8:88:12 | "bar" |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:3:117:8 | Pair | literals.rb:117:3:117:5 | :foo | literals.rb:117:8:117:8 | 1 |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:11:117:19 | Pair | literals.rb:117:11:117:14 | :bar | literals.rb:117:19:117:19 | 2 |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:22:117:31 | Pair | literals.rb:117:22:117:26 | "baz" | literals.rb:117:31:117:31 | 3 |
+| literals.rb:118:1:118:17 | {...} | literals.rb:118:3:118:8 | Pair | literals.rb:118:3:118:5 | :foo | literals.rb:118:8:118:8 | 7 |
finiteRangeLiterals
-| literals.rb:117:2:117:6 | _ .. _ | literals.rb:117:2:117:2 | 1 | literals.rb:117:5:117:6 | 10 |
-| literals.rb:118:2:118:7 | _ ... _ | literals.rb:118:2:118:2 | 1 | literals.rb:118:6:118:7 | 10 |
-| literals.rb:119:2:119:7 | _ .. _ | literals.rb:119:2:119:2 | 1 | literals.rb:119:7:119:7 | 0 |
-| literals.rb:120:2:120:11 | _ .. _ | literals.rb:120:2:120:6 | call to start | literals.rb:120:9:120:11 | ... + ... |
+| literals.rb:121:2:121:6 | _ .. _ | literals.rb:121:2:121:2 | 1 | literals.rb:121:5:121:6 | 10 |
+| literals.rb:122:2:122:7 | _ ... _ | literals.rb:122:2:122:2 | 1 | literals.rb:122:6:122:7 | 10 |
+| literals.rb:123:2:123:7 | _ .. _ | literals.rb:123:2:123:2 | 1 | literals.rb:123:7:123:7 | 0 |
+| literals.rb:124:2:124:11 | _ .. _ | literals.rb:124:2:124:6 | call to start | literals.rb:124:9:124:11 | ... + ... |
beginlessRangeLiterals
-| literals.rb:122:2:122:4 | _ .. _ | literals.rb:122:4:122:4 | 1 |
+| literals.rb:126:2:126:4 | _ .. _ | literals.rb:126:4:126:4 | 1 |
endlessRangeLiterals
-| literals.rb:121:2:121:4 | _ .. _ | literals.rb:121:2:121:2 | 1 |
-| literals.rb:123:2:123:4 | _ .. _ | literals.rb:123:2:123:2 | 0 |
+| literals.rb:125:2:125:4 | _ .. _ | literals.rb:125:2:125:2 | 1 |
+| literals.rb:127:2:127:4 | _ .. _ | literals.rb:127:2:127:2 | 0 |
inclusiveRangeLiterals
-| literals.rb:117:2:117:6 | _ .. _ |
-| literals.rb:119:2:119:7 | _ .. _ |
-| literals.rb:120:2:120:11 | _ .. _ |
-| literals.rb:121:2:121:4 | _ .. _ |
-| literals.rb:122:2:122:4 | _ .. _ |
-| literals.rb:123:2:123:4 | _ .. _ |
+| literals.rb:121:2:121:6 | _ .. _ |
+| literals.rb:123:2:123:7 | _ .. _ |
+| literals.rb:124:2:124:11 | _ .. _ |
+| literals.rb:125:2:125:4 | _ .. _ |
+| literals.rb:126:2:126:4 | _ .. _ |
+| literals.rb:127:2:127:4 | _ .. _ |
exclusiveRangeLiterals
-| literals.rb:118:2:118:7 | _ ... _ |
+| literals.rb:122:2:122:7 | _ ... _ |
numericLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
@@ -677,46 +677,46 @@ numericLiterals
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
integerLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
@@ -740,46 +740,46 @@ integerLiterals
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
floatLiterals
| literals.rb:30:1:30:5 | 12.34 | FloatLiteral | 12.34 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 1234e-2 |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.rb b/ruby/ql/test/library-tests/ast/literals/literals.rb
index a264a6d0003..1c1304d9eef 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.rb
+++ b/ruby/ql/test/library-tests/ast/literals/literals.rb
@@ -65,6 +65,10 @@ TRUE
"foo #{ "bar #{ 2 + 3 } baz" } qux" # interpolation containing string containing interpolation
"foo #{ blah(); 1+9 }" # multiple statements in interpolation
+
+
+
+
# characters
?x
?\n
From 32c93e70e2612bfbc76b11f17b59d58709342985 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 7 Dec 2021 17:55:46 +1300
Subject: [PATCH 012/296] Include simple interpolations in getValueText
When calculating `StringlikeLiteral.getValueText`, include results from
interpolations where we can determine their string value. For example:
b = "b" # local variable
D = "d" # constant
"a#{b}c" # getValueText() = "abc"
"a#{b}c{D}" # getValueText() = "abcd"
/#a#{b}c{D}/ # getValueText() = "abcd"
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 7 +-
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 39 ++-
ruby/ql/test/library-tests/ast/Ast.expected | 98 ++++++-
.../library-tests/ast/AstDesugar.expected | 20 ++
.../test/library-tests/ast/ValueText.expected | 51 +++-
.../ast/literals/literals.expected | 276 ++++++++++++------
.../library-tests/ast/literals/literals.rb | 30 +-
.../test/library-tests/ast/misc/misc.expected | 4 +-
.../test/library-tests/regexp/parse.expected | 11 +
ruby/ql/test/library-tests/regexp/regexp.rb | 6 +-
10 files changed, 411 insertions(+), 131 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 1be956c9a33..181c23fbf6e 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -3,6 +3,7 @@ private import codeql.ruby.security.performance.RegExpTreeView as RETV
private import internal.AST
private import internal.Scope
private import internal.TreeSitter
+private import codeql.ruby.controlflow.CfgNodes
/**
* A literal.
@@ -411,14 +412,14 @@ class StringlikeLiteral extends Literal, TStringlikeLiteral {
}
override string getValueText() {
- // 0 components should result in the empty string
- // if there are any interpolations, there should be no result
- // otherwise, concatenate all the components
forall(StringComponent c | c = this.getComponent(_) |
not c instanceof StringInterpolationComponent
) and
result =
concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
+ or
+ exists(this.getComponent(_)) and
+ result = this.getAControlFlowNode().(ExprNodes::StringlikeLiteralCfgNode).getValueText()
}
override string toString() {
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 5ea3038c3a4..369a79209ab 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -128,6 +128,8 @@ class ReturningCfgNode extends AstCfgNode {
/** A control-flow node that wraps a `StringComponent` AST expression. */
class StringComponentCfgNode extends AstCfgNode {
StringComponentCfgNode() { this.getNode() instanceof StringComponent }
+
+ string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
private Expr desugar(Expr n) {
@@ -463,8 +465,13 @@ module ExprNodes {
}
/** A control-flow node that wraps a `StringInterpolationComponent` AST expression. */
- class StringInterpolationComponentCfgNode extends StmtSequenceCfgNode {
+ class StringInterpolationComponentCfgNode extends StringComponentCfgNode, StmtSequenceCfgNode {
StringInterpolationComponentCfgNode() { this.getNode() instanceof StringInterpolationComponent }
+
+ // If last statement in the interpolation is a constant or local variable read,
+ // we attempt to look up its string value.
+ // If there's a result, we return that as the string value of the interpolation.
+ final override string getValueText() { result = this.getLastStmt().getValueText() }
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
@@ -477,8 +484,36 @@ module ExprNodes {
final override StringlikeLiteral getExpr() { result = super.getExpr() }
+ /** Gets the `n`th component of this `StringlikeLiteral` */
+ StringComponentCfgNode getComponent(int n) { result.getNode() = e.getComponent(n) }
+
/** Gets a component of this `StringlikeLiteral` */
- StringComponentCfgNode getAComponent() { e.hasCfgChild(e.getComponent(_), this, result) }
+ StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
+
+ // 0 components results in the empty string
+ // if all interpolations have a known string value, we will get a result
+ language[monotonicAggregates]
+ override string getValueText() {
+ result = e.getValueText()
+ or
+ result =
+ concat(StringComponent c, int i |
+ c = e.getComponent(i)
+ |
+ getComponentValueText(c) order by i
+ )
+ }
+
+ /**
+ * Get the `ValueText()` of a `StringComponent`.
+ * If the component has a CFG node, defer to that (in order to resolve variables in interpolations).
+ * Otherwise, defer to the AST node.
+ */
+ private string getComponentValueText(StringComponent c) {
+ exists(StringComponentCfgNode n | n.getNode() = c | result = n.getValueText())
+ or
+ not exists(StringComponentCfgNode n | n.getNode() = c) and result = c.getValueText()
+ }
}
/** A control-flow node that wraps a `StringLiteral` AST expression. */
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index e3630cf4ac2..57c9704bc40 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -1515,6 +1515,22 @@ literals/literals.rb:
# 66| getStmt: [AddExpr] ... + ...
# 66| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 66| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 9
+# 67| getStmt: [AssignExpr] ... = ...
+# 67| getAnOperand/getLeftOperand: [LocalVariableAccess] bar
+# 67| getAnOperand/getRightOperand: [StringLiteral] "bar"
+# 67| getComponent: [StringTextComponent] bar
+# 68| getStmt: [AssignExpr] ... = ...
+# 68| getAnOperand/getLeftOperand: [ConstantAssignment] BAR
+# 68| getAnOperand/getRightOperand: [StringLiteral] "bar"
+# 68| getComponent: [StringTextComponent] bar
+# 69| getStmt: [StringLiteral] "foo #{...}"
+# 69| getComponent: [StringTextComponent] foo
+# 69| getComponent: [StringInterpolationComponent] #{...}
+# 69| getStmt: [LocalVariableAccess] bar
+# 70| getStmt: [StringLiteral] "foo #{...}"
+# 70| getComponent: [StringTextComponent] foo
+# 70| getComponent: [StringInterpolationComponent] #{...}
+# 70| getStmt: [ConstantReadAccess] BAR
# 73| getStmt: [CharacterLiteral] ?x
# 74| getStmt: [CharacterLiteral] ?\n
# 75| getStmt: [CharacterLiteral] ?\s
@@ -1539,14 +1555,20 @@ literals/literals.rb:
# 89| getComponent: [StringTextComponent] wibble
# 90| getStmt: [SymbolLiteral] :"wibble wobble"
# 90| getComponent: [StringTextComponent] wibble wobble
-# 91| getStmt: [SymbolLiteral] :"foo_#{...}"
+# 91| getStmt: [SymbolLiteral] :"foo_#{...}_#{...}_#{...}"
# 91| getComponent: [StringTextComponent] foo_
# 91| getComponent: [StringInterpolationComponent] #{...}
# 91| getStmt: [AddExpr] ... + ...
# 91| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 91| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 92| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
-# 92| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
+# 91| getComponent: [StringTextComponent] _
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [LocalVariableAccess] bar
+# 91| getComponent: [StringTextComponent] _
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [ConstantReadAccess] BAR
+# 92| getStmt: [SymbolLiteral] :"foo_#{ 2 + 2}_#{bar}_#{BAR}"
+# 92| getComponent: [StringTextComponent] foo_#{ 2 + 2}_#{bar}_#{BAR}
# 93| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
# 93| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
# 96| getStmt: [ArrayLiteral] [...]
@@ -1589,6 +1611,12 @@ literals/literals.rb:
# 105| getStmt: [AddExpr] ... + ...
# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getElement: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [LocalVariableAccess] bar
+# 105| getElement: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [ConstantReadAccess] BAR
# 105| getElement: [StringLiteral] "baz"
# 105| getComponent: [StringTextComponent] baz
# 106| getStmt: [ArrayLiteral] %w(...)
@@ -1596,6 +1624,10 @@ literals/literals.rb:
# 106| getComponent: [StringTextComponent] foo
# 106| getElement: [StringLiteral] "bar#{1+1}"
# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getElement: [StringLiteral] "#{bar}"
+# 106| getComponent: [StringTextComponent] #{bar}
+# 106| getElement: [StringLiteral] "#{BAR}"
+# 106| getComponent: [StringTextComponent] #{BAR}
# 106| getElement: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
# 109| getStmt: [ArrayLiteral] %i(...)
@@ -1622,6 +1654,12 @@ literals/literals.rb:
# 112| getStmt: [AddExpr] ... + ...
# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getElement: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [LocalVariableAccess] bar
+# 112| getElement: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [ConstantReadAccess] BAR
# 112| getElement: [SymbolLiteral] :"baz"
# 112| getComponent: [StringTextComponent] baz
# 113| getStmt: [ArrayLiteral] %i(...)
@@ -1637,6 +1675,10 @@ literals/literals.rb:
# 113| getComponent: [StringTextComponent] 4
# 113| getElement: [SymbolLiteral] :"}"
# 113| getComponent: [StringTextComponent] }
+# 113| getElement: [SymbolLiteral] :"#{bar}"
+# 113| getComponent: [StringTextComponent] #{bar}
+# 113| getElement: [SymbolLiteral] :"#{BAR}"
+# 113| getComponent: [StringTextComponent] #{BAR}
# 113| getElement: [SymbolLiteral] :"baz"
# 113| getComponent: [StringTextComponent] baz
# 116| getStmt: [HashLiteral] {...}
@@ -1656,7 +1698,7 @@ literals/literals.rb:
# 118| getKey: [SymbolLiteral] :foo
# 118| getValue: [IntegerLiteral] 7
# 118| getElement: [HashSplatExpr] ** ...
-# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
+# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to baz
# 118| getReceiver: [Self, SelfVariableAccess] self
# 121| getStmt: [ParenthesizedExpr] ( ... )
# 121| getStmt: [RangeLiteral] _ .. _
@@ -1692,12 +1734,18 @@ literals/literals.rb:
# 130| getComponent: [StringTextComponent] ls -l
# 131| getStmt: [SubshellLiteral] `ls -l`
# 131| getComponent: [StringTextComponent] ls -l
-# 132| getStmt: [SubshellLiteral] `du -d #{...}`
+# 132| getStmt: [SubshellLiteral] `du -d #{...} #{...} #{...}`
# 132| getComponent: [StringTextComponent] du -d
# 132| getComponent: [StringInterpolationComponent] #{...}
# 132| getStmt: [AddExpr] ... + ...
# 132| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 132| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 132| getComponent: [StringTextComponent]
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [LocalVariableAccess] bar
+# 132| getComponent: [StringTextComponent]
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [ConstantReadAccess] BAR
# 133| getStmt: [SubshellLiteral] `du -d #{...}`
# 133| getComponent: [StringTextComponent] du -d
# 133| getComponent: [StringInterpolationComponent] #{...}
@@ -1732,13 +1780,31 @@ literals/literals.rb:
# 139| getComponent: [StringEscapeSequenceComponent] \s
# 139| getComponent: [StringTextComponent] bar
# 139| getComponent: [StringEscapeSequenceComponent] \S
-# 140| getStmt: [RegExpLiteral] /foo#{...}bar/
+# 140| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
+# 140| getParsed: [RegExpSequence] foo2barbarbar
+# 140| 0: [RegExpConstant, RegExpNormalChar] f
+# 140| 1: [RegExpConstant, RegExpNormalChar] o
+# 140| 2: [RegExpConstant, RegExpNormalChar] o
+# 140| 3: [RegExpConstant, RegExpNormalChar] 2
+# 140| 4: [RegExpConstant, RegExpNormalChar] b
+# 140| 5: [RegExpConstant, RegExpNormalChar] a
+# 140| 6: [RegExpConstant, RegExpNormalChar] r
+# 140| 7: [RegExpConstant, RegExpNormalChar] b
+# 140| 8: [RegExpConstant, RegExpNormalChar] a
+# 140| 9: [RegExpConstant, RegExpNormalChar] r
+# 140| 10: [RegExpConstant, RegExpNormalChar] b
+# 140| 11: [RegExpConstant, RegExpNormalChar] a
+# 140| 12: [RegExpConstant, RegExpNormalChar] r
# 140| getComponent: [StringTextComponent] foo
# 140| getComponent: [StringInterpolationComponent] #{...}
# 140| getStmt: [AddExpr] ... + ...
# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 140| getComponent: [StringTextComponent] bar
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [LocalVariableAccess] bar
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [ConstantReadAccess] BAR
# 141| getStmt: [RegExpLiteral] /foo/
# 141| getParsed: [RegExpSequence] foo
# 141| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1773,13 +1839,31 @@ literals/literals.rb:
# 145| getComponent: [StringEscapeSequenceComponent] \s
# 145| getComponent: [StringTextComponent] bar
# 145| getComponent: [StringEscapeSequenceComponent] \S
-# 146| getStmt: [RegExpLiteral] /foo#{...}bar/
+# 146| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
+# 146| getParsed: [RegExpSequence] foo2barbarbar
+# 146| 0: [RegExpConstant, RegExpNormalChar] f
+# 146| 1: [RegExpConstant, RegExpNormalChar] o
+# 146| 2: [RegExpConstant, RegExpNormalChar] o
+# 146| 3: [RegExpConstant, RegExpNormalChar] 2
+# 146| 4: [RegExpConstant, RegExpNormalChar] b
+# 146| 5: [RegExpConstant, RegExpNormalChar] a
+# 146| 6: [RegExpConstant, RegExpNormalChar] r
+# 146| 7: [RegExpConstant, RegExpNormalChar] b
+# 146| 8: [RegExpConstant, RegExpNormalChar] a
+# 146| 9: [RegExpConstant, RegExpNormalChar] r
+# 146| 10: [RegExpConstant, RegExpNormalChar] b
+# 146| 11: [RegExpConstant, RegExpNormalChar] a
+# 146| 12: [RegExpConstant, RegExpNormalChar] r
# 146| getComponent: [StringTextComponent] foo
# 146| getComponent: [StringInterpolationComponent] #{...}
# 146| getStmt: [AddExpr] ... + ...
# 146| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 146| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 146| getComponent: [StringTextComponent] bar
+# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getStmt: [LocalVariableAccess] bar
+# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getStmt: [ConstantReadAccess] BAR
# 147| getStmt: [RegExpLiteral] /foo/
# 147| getParsed: [RegExpSequence] foo
# 147| 0: [RegExpConstant, RegExpNormalChar] f
diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected
index 40548cba53c..6acafd116c5 100644
--- a/ruby/ql/test/library-tests/ast/AstDesugar.expected
+++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected
@@ -350,6 +350,12 @@ literals/literals.rb:
# 105| getStmt: [AddExpr] ... + ...
# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getArgument: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [LocalVariableAccess] bar
+# 105| getArgument: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [ConstantReadAccess] BAR
# 105| getArgument: [StringLiteral] "baz"
# 105| getComponent: [StringTextComponent] baz
# 106| [ArrayLiteral] %w(...)
@@ -359,6 +365,10 @@ literals/literals.rb:
# 106| getComponent: [StringTextComponent] foo
# 106| getArgument: [StringLiteral] "bar#{1+1}"
# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getArgument: [StringLiteral] "#{bar}"
+# 106| getComponent: [StringTextComponent] #{bar}
+# 106| getArgument: [StringLiteral] "#{BAR}"
+# 106| getComponent: [StringTextComponent] #{BAR}
# 106| getArgument: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
# 109| [ArrayLiteral] %i(...)
@@ -393,6 +403,12 @@ literals/literals.rb:
# 112| getStmt: [AddExpr] ... + ...
# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getArgument: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [LocalVariableAccess] bar
+# 112| getArgument: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [ConstantReadAccess] BAR
# 112| getArgument: [SymbolLiteral] :"baz"
# 112| getComponent: [StringTextComponent] baz
# 113| [ArrayLiteral] %i(...)
@@ -410,6 +426,10 @@ literals/literals.rb:
# 113| getComponent: [StringTextComponent] 4
# 113| getArgument: [SymbolLiteral] :"}"
# 113| getComponent: [StringTextComponent] }
+# 113| getArgument: [SymbolLiteral] :"#{bar}"
+# 113| getComponent: [StringTextComponent] #{bar}
+# 113| getArgument: [SymbolLiteral] :"#{BAR}"
+# 113| getComponent: [StringTextComponent] #{BAR}
# 113| getArgument: [SymbolLiteral] :"baz"
# 113| getComponent: [StringTextComponent] baz
control/loops.rb:
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index aae39cebac9..e2a318c333c 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -389,9 +389,11 @@
| literals/literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals/literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals/literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
+| literals/literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
| literals/literals.rb:58:13:58:13 | 2 | 2 |
| literals/literals.rb:58:13:58:17 | ... + ... | 4 |
| literals/literals.rb:58:17:58:17 | 2 | 2 |
+| literals/literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals/literals.rb:59:15:59:15 | 3 | 3 |
| literals/literals.rb:59:15:59:19 | ... + ... | 7 |
| literals/literals.rb:59:19:59:19 | 4 | 4 |
@@ -404,16 +406,26 @@
| literals/literals.rb:63:9:63:13 | "bar" | bar |
| literals/literals.rb:63:15:63:19 | "baz" | baz |
| literals/literals.rb:64:1:64:5 | "foo" | foo |
+| literals/literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals/literals.rb:64:14:64:14 | 1 | 1 |
| literals/literals.rb:64:14:64:18 | ... * ... | 1 |
| literals/literals.rb:64:18:64:18 | 1 | 1 |
| literals/literals.rb:64:23:64:27 | "baz" | baz |
+| literals/literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals/literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
| literals/literals.rb:65:17:65:17 | 2 | 2 |
| literals/literals.rb:65:17:65:21 | ... + ... | 5 |
| literals/literals.rb:65:21:65:21 | 3 | 3 |
+| literals/literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
| literals/literals.rb:66:17:66:17 | 1 | 1 |
| literals/literals.rb:66:17:66:19 | ... + ... | 10 |
| literals/literals.rb:66:19:66:19 | 9 | 9 |
+| literals/literals.rb:67:7:67:11 | "bar" | bar |
+| literals/literals.rb:68:7:68:11 | "bar" | bar |
+| literals/literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals/literals.rb:69:9:69:11 | bar | bar |
+| literals/literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
+| literals/literals.rb:70:9:70:11 | BAR | bar |
| literals/literals.rb:73:1:73:2 | ?x | ?x |
| literals/literals.rb:74:1:74:3 | ?\\n | ?\\n |
| literals/literals.rb:75:1:75:3 | ?\\s | ?\\s |
@@ -431,10 +443,13 @@
| literals/literals.rb:88:8:88:12 | "bar" | bar |
| literals/literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals/literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals/literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
| literals/literals.rb:91:10:91:10 | 2 | 2 |
| literals/literals.rb:91:10:91:14 | ... + ... | 4 |
| literals/literals.rb:91:14:91:14 | 2 | 2 |
-| literals/literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals/literals.rb:91:19:91:21 | bar | bar |
+| literals/literals.rb:91:26:91:28 | BAR | bar |
+| literals/literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals/literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals/literals.rb:97:2:97:2 | 1 | 1 |
| literals/literals.rb:97:5:97:5 | 2 | 2 |
@@ -454,13 +469,20 @@
| literals/literals.rb:104:8:104:10 | "bar" | bar |
| literals/literals.rb:104:12:104:14 | "baz" | baz |
| literals/literals.rb:105:4:105:6 | "foo" | foo |
+| literals/literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
| literals/literals.rb:105:13:105:13 | 1 | 1 |
| literals/literals.rb:105:13:105:15 | ... + ... | 2 |
| literals/literals.rb:105:15:105:15 | 1 | 1 |
-| literals/literals.rb:105:18:105:20 | "baz" | baz |
+| literals/literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals/literals.rb:105:20:105:22 | bar | bar |
+| literals/literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals/literals.rb:105:27:105:29 | BAR | bar |
+| literals/literals.rb:105:32:105:34 | "baz" | baz |
| literals/literals.rb:106:4:106:6 | "foo" | foo |
| literals/literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals/literals.rb:106:18:106:20 | "baz" | baz |
+| literals/literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals/literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals/literals.rb:106:32:106:34 | "baz" | baz |
| literals/literals.rb:110:4:110:6 | :"foo" | foo |
| literals/literals.rb:110:8:110:10 | :"bar" | bar |
| literals/literals.rb:110:12:110:14 | :"baz" | baz |
@@ -468,17 +490,24 @@
| literals/literals.rb:111:8:111:10 | :"bar" | bar |
| literals/literals.rb:111:12:111:14 | :"baz" | baz |
| literals/literals.rb:112:4:112:6 | :"foo" | foo |
+| literals/literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
| literals/literals.rb:112:14:112:14 | 2 | 2 |
| literals/literals.rb:112:14:112:18 | ... + ... | 6 |
| literals/literals.rb:112:18:112:18 | 4 | 4 |
-| literals/literals.rb:112:22:112:24 | :"baz" | baz |
+| literals/literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals/literals.rb:112:24:112:26 | bar | bar |
+| literals/literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals/literals.rb:112:31:112:33 | BAR | bar |
+| literals/literals.rb:112:36:112:38 | :"baz" | baz |
| literals/literals.rb:113:4:113:6 | :"foo" | foo |
| literals/literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals/literals.rb:113:14:113:14 | :"2" | 2 |
| literals/literals.rb:113:16:113:16 | :"+" | + |
| literals/literals.rb:113:18:113:18 | :"4" | 4 |
| literals/literals.rb:113:20:113:20 | :"}" | } |
-| literals/literals.rb:113:22:113:24 | :"baz" | baz |
+| literals/literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals/literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals/literals.rb:113:36:113:38 | :"baz" | baz |
| literals/literals.rb:117:3:117:5 | :foo | foo |
| literals/literals.rb:117:8:117:8 | 1 | 1 |
| literals/literals.rb:117:11:117:14 | :bar | bar |
@@ -502,9 +531,13 @@
| literals/literals.rb:127:6:127:6 | 1 | 1 |
| literals/literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals/literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals/literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
| literals/literals.rb:132:11:132:11 | 1 | 1 |
| literals/literals.rb:132:11:132:15 | ... + ... | 2 |
| literals/literals.rb:132:15:132:15 | 1 | 1 |
+| literals/literals.rb:132:21:132:23 | bar | bar |
+| literals/literals.rb:132:28:132:30 | BAR | bar |
+| literals/literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
| literals/literals.rb:133:13:133:13 | 5 | 5 |
| literals/literals.rb:133:13:133:17 | ... - ... | 1 |
| literals/literals.rb:133:17:133:17 | 4 | 4 |
@@ -512,17 +545,23 @@
| literals/literals.rb:137:1:137:5 | /foo/ | foo |
| literals/literals.rb:138:1:138:6 | /foo/ | foo |
| literals/literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals/literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals/literals.rb:140:8:140:8 | 1 | 1 |
| literals/literals.rb:140:8:140:12 | ... + ... | 2 |
| literals/literals.rb:140:12:140:12 | 1 | 1 |
+| literals/literals.rb:140:20:140:22 | bar | bar |
+| literals/literals.rb:140:26:140:28 | BAR | bar |
| literals/literals.rb:141:1:141:8 | /foo/ | foo |
| literals/literals.rb:142:1:142:4 | // | |
| literals/literals.rb:143:1:143:7 | /foo/ | foo |
| literals/literals.rb:144:1:144:8 | /foo/ | foo |
| literals/literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals/literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals/literals.rb:146:10:146:10 | 1 | 1 |
| literals/literals.rb:146:10:146:14 | ... + ... | 2 |
| literals/literals.rb:146:14:146:14 | 1 | 1 |
+| literals/literals.rb:146:22:146:24 | bar | bar |
+| literals/literals.rb:146:28:146:30 | BAR | bar |
| literals/literals.rb:147:1:147:10 | /foo/ | foo |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -538,6 +577,7 @@
| misc/misc.rb:3:18:3:21 | foo= | foo= |
| misc/misc.rb:3:24:3:25 | [] | [] |
| misc/misc.rb:3:28:3:30 | []= | []= |
+| misc/misc.rb:4:7:4:19 | :"foo_#{...}" | foo_bar |
| misc/misc.rb:4:15:4:17 | bar | bar |
| misc/misc.rb:5:7:5:9 | nil | nil |
| misc/misc.rb:5:12:5:15 | true | true |
@@ -550,6 +590,7 @@
| misc/misc.rb:8:12:8:14 | []= | []= |
| misc/misc.rb:9:7:9:11 | super | super |
| misc/misc.rb:9:13:9:16 | self | self |
+| misc/misc.rb:10:7:10:17 | :"\\n#{...}" | \\nbar |
| misc/misc.rb:10:13:10:15 | bar | bar |
| misc/misc.rb:10:19:10:24 | :"foo" | foo |
| modules/classes.rb:11:28:11:31 | :baz | baz |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.expected b/ruby/ql/test/library-tests/ast/literals/literals.expected
index cfcfb81abb1..a84d52fe2b0 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.expected
+++ b/ruby/ql/test/library-tests/ast/literals/literals.expected
@@ -35,10 +35,10 @@ allLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | StringLiteral | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | StringLiteral | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | StringLiteral | 2 + 2 = 4 |
| literals.rb:58:13:58:13 | 2 | IntegerLiteral | 2 |
| literals.rb:58:17:58:17 | 2 | IntegerLiteral | 2 |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | StringLiteral | |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | StringLiteral | 3 + 4 = 7 |
| literals.rb:59:15:59:15 | 3 | IntegerLiteral | 3 |
| literals.rb:59:19:59:19 | 4 | IntegerLiteral | 4 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | StringLiteral | 2 + 2 = #{ 2 + 2 } |
@@ -50,17 +50,21 @@ allLiterals
| literals.rb:63:9:63:13 | "bar" | StringLiteral | bar |
| literals.rb:63:15:63:19 | "baz" | StringLiteral | baz |
| literals.rb:64:1:64:5 | "foo" | StringLiteral | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | StringLiteral | |
+| literals.rb:64:7:64:21 | "bar#{...}" | StringLiteral | bar1 |
| literals.rb:64:14:64:14 | 1 | IntegerLiteral | 1 |
| literals.rb:64:18:64:18 | 1 | IntegerLiteral | 1 |
| literals.rb:64:23:64:27 | "baz" | StringLiteral | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | StringLiteral | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | StringLiteral | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | bar 5 baz |
| literals.rb:65:17:65:17 | 2 | IntegerLiteral | 2 |
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
-| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | |
+| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | foo 10 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
+| literals.rb:67:7:67:11 | "bar" | StringLiteral | bar |
+| literals.rb:68:7:68:11 | "bar" | StringLiteral | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | foo bar |
| literals.rb:73:1:73:2 | ?x | CharacterLiteral | ?x |
| literals.rb:74:1:74:3 | ?\\n | CharacterLiteral | ?\\n |
| literals.rb:75:1:75:3 | ?\\s | CharacterLiteral | ?\\s |
@@ -79,10 +83,10 @@ allLiterals
| literals.rb:88:8:88:12 | "bar" | StringLiteral | bar |
| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | foo_4_bar_bar |
| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | SymbolLiteral | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
| literals.rb:96:1:96:2 | [...] | ArrayLiteral | |
| literals.rb:97:1:97:9 | [...] | ArrayLiteral | |
@@ -108,16 +112,20 @@ allLiterals
| literals.rb:104:4:104:6 | "foo" | StringLiteral | foo |
| literals.rb:104:8:104:10 | "bar" | StringLiteral | bar |
| literals.rb:104:12:104:14 | "baz" | StringLiteral | baz |
-| literals.rb:105:1:105:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:1:105:35 | %w(...) | ArrayLiteral | |
| literals.rb:105:4:105:6 | "foo" | StringLiteral | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | |
+| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | bar2 |
| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:105:18:105:20 | "baz" | StringLiteral | baz |
-| literals.rb:106:1:106:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:18:105:23 | "#{...}" | StringLiteral | bar |
+| literals.rb:105:25:105:30 | "#{...}" | StringLiteral | bar |
+| literals.rb:105:32:105:34 | "baz" | StringLiteral | baz |
+| literals.rb:106:1:106:35 | %w(...) | ArrayLiteral | |
| literals.rb:106:4:106:6 | "foo" | StringLiteral | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | StringLiteral | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | StringLiteral | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | StringLiteral | baz |
| literals.rb:109:1:109:4 | %i(...) | ArrayLiteral | |
| literals.rb:110:1:110:15 | %i(...) | ArrayLiteral | |
| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | foo |
@@ -127,20 +135,24 @@ allLiterals
| literals.rb:111:4:111:6 | :"foo" | SymbolLiteral | foo |
| literals.rb:111:8:111:10 | :"bar" | SymbolLiteral | bar |
| literals.rb:111:12:111:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:112:1:112:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:1:112:39 | %i(...) | ArrayLiteral | |
| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | |
+| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | bar6 |
| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:113:1:113:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral | bar |
+| literals.rb:112:36:112:38 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:1:113:39 | %i(...) | ArrayLiteral | |
| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | foo |
| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | bar#{ |
| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 2 |
| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | + |
| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 4 |
| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | } |
-| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | SymbolLiteral | baz |
| literals.rb:116:1:116:2 | {...} | HashLiteral | |
| literals.rb:117:1:117:33 | {...} | HashLiteral | |
| literals.rb:117:3:117:5 | :foo | SymbolLiteral | foo |
@@ -173,17 +185,17 @@ allLiterals
| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | du -d 2 bar bar |
| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | du -d 1 |
| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
| literals.rb:136:1:136:2 | // | RegExpLiteral | |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | foo |
| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
@@ -191,7 +203,7 @@ allLiterals
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
@@ -218,8 +230,8 @@ stringlikeLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
| literals.rb:61:1:61:22 | "3 + 4 = #{ 3 + 4 }" | 3 + 4 = #{ 3 + 4 } |
| literals.rb:62:1:62:5 | "foo" | foo |
@@ -229,11 +241,15 @@ stringlikeLiterals
| literals.rb:63:9:63:13 | "bar" | bar |
| literals.rb:63:15:63:19 | "baz" | baz |
| literals.rb:64:1:64:5 | "foo" | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | |
+| literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals.rb:64:23:64:27 | "baz" | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | |
-| literals.rb:66:1:66:22 | "foo #{...}" | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
+| literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
+| literals.rb:67:7:67:11 | "bar" | bar |
+| literals.rb:68:7:68:11 | "bar" | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
| literals.rb:84:1:84:3 | :"" | |
| literals.rb:85:1:85:6 | :hello | hello |
| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
@@ -242,8 +258,8 @@ stringlikeLiterals
| literals.rb:88:8:88:12 | "bar" | bar |
| literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals.rb:103:4:103:6 | "foo" | foo |
| literals.rb:103:8:103:10 | "bar" | bar |
@@ -252,11 +268,15 @@ stringlikeLiterals
| literals.rb:104:8:104:10 | "bar" | bar |
| literals.rb:104:12:104:14 | "baz" | baz |
| literals.rb:105:4:105:6 | "foo" | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | |
-| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
+| literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals.rb:105:32:105:34 | "baz" | baz |
| literals.rb:106:4:106:6 | "foo" | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | baz |
| literals.rb:110:4:110:6 | :"foo" | foo |
| literals.rb:110:8:110:10 | :"bar" | bar |
| literals.rb:110:12:110:14 | :"baz" | baz |
@@ -264,34 +284,38 @@ stringlikeLiterals
| literals.rb:111:8:111:10 | :"bar" | bar |
| literals.rb:111:12:111:14 | :"baz" | baz |
| literals.rb:112:4:112:6 | :"foo" | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | |
-| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
+| literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals.rb:112:36:112:38 | :"baz" | baz |
| literals.rb:113:4:113:6 | :"foo" | foo |
| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals.rb:113:14:113:14 | :"2" | 2 |
| literals.rb:113:16:113:16 | :"+" | + |
| literals.rb:113:18:113:18 | :"4" | 4 |
| literals.rb:113:20:113:20 | :"}" | } |
-| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | baz |
| literals.rb:117:3:117:5 | :foo | foo |
| literals.rb:117:11:117:14 | :bar | bar |
| literals.rb:117:22:117:26 | "baz" | baz |
| literals.rb:118:3:118:5 | :foo | foo |
| literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | |
-| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
+| literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
| literals.rb:136:1:136:2 | // | |
| literals.rb:137:1:137:5 | /foo/ | foo |
| literals.rb:138:1:138:6 | /foo/ | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:141:1:141:8 | /foo/ | foo |
| literals.rb:142:1:142:4 | // | |
| literals.rb:143:1:143:7 | /foo/ | foo |
| literals.rb:144:1:144:8 | /foo/ | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:147:1:147:10 | /foo/ | foo |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -316,8 +340,8 @@ stringLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
| literals.rb:61:1:61:22 | "3 + 4 = #{ 3 + 4 }" | 3 + 4 = #{ 3 + 4 } |
| literals.rb:62:1:62:5 | "foo" | foo |
@@ -327,11 +351,15 @@ stringLiterals
| literals.rb:63:9:63:13 | "bar" | bar |
| literals.rb:63:15:63:19 | "baz" | baz |
| literals.rb:64:1:64:5 | "foo" | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | |
+| literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals.rb:64:23:64:27 | "baz" | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | |
-| literals.rb:66:1:66:22 | "foo #{...}" | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
+| literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
+| literals.rb:67:7:67:11 | "bar" | bar |
+| literals.rb:68:7:68:11 | "bar" | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
| literals.rb:88:8:88:12 | "bar" | bar |
| literals.rb:103:4:103:6 | "foo" | foo |
| literals.rb:103:8:103:10 | "bar" | bar |
@@ -340,11 +368,15 @@ stringLiterals
| literals.rb:104:8:104:10 | "bar" | bar |
| literals.rb:104:12:104:14 | "baz" | baz |
| literals.rb:105:4:105:6 | "foo" | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | |
-| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
+| literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals.rb:105:32:105:34 | "baz" | baz |
| literals.rb:106:4:106:6 | "foo" | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | baz |
| literals.rb:117:22:117:26 | "baz" | baz |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -354,13 +386,13 @@ regExpLiterals
| literals.rb:137:1:137:5 | /foo/ | foo | |
| literals.rb:138:1:138:6 | /foo/ | foo | i |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
| literals.rb:142:1:142:4 | // | | |
| literals.rb:143:1:143:7 | /foo/ | foo | |
| literals.rb:144:1:144:8 | /foo/ | foo | i |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
symbolLiterals
| literals.rb:84:1:84:3 | :"" | |
@@ -370,8 +402,8 @@ symbolLiterals
| literals.rb:88:3:88:5 | :foo | foo |
| literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals.rb:110:4:110:6 | :"foo" | foo |
| literals.rb:110:8:110:10 | :"bar" | bar |
@@ -380,23 +412,27 @@ symbolLiterals
| literals.rb:111:8:111:10 | :"bar" | bar |
| literals.rb:111:12:111:14 | :"baz" | baz |
| literals.rb:112:4:112:6 | :"foo" | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | |
-| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
+| literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals.rb:112:36:112:38 | :"baz" | baz |
| literals.rb:113:4:113:6 | :"foo" | foo |
| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals.rb:113:14:113:14 | :"2" | 2 |
| literals.rb:113:16:113:16 | :"+" | + |
| literals.rb:113:18:113:18 | :"4" | 4 |
| literals.rb:113:20:113:20 | :"}" | } |
-| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | baz |
| literals.rb:117:3:117:5 | :foo | foo |
| literals.rb:117:11:117:14 | :bar | bar |
| literals.rb:118:3:118:5 | :foo | foo |
subshellLiterals
| literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | |
-| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
+| literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
stringComponents
| literals.rb:48:1:48:7 | "hello" | StringLiteral | 0 | literals.rb:48:2:48:6 | hello | StringTextComponent |
| literals.rb:49:1:49:9 | "goodbye" | StringLiteral | 0 | literals.rb:49:2:49:8 | goodbye | StringTextComponent |
@@ -436,14 +472,24 @@ stringComponents
| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | 2 | literals.rb:65:24:65:27 | baz | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 0 | literals.rb:66:2:66:5 | foo | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 1 | literals.rb:66:6:66:21 | #{...} | StringInterpolationComponent |
+| literals.rb:67:7:67:11 | "bar" | StringLiteral | 0 | literals.rb:67:8:67:10 | bar | StringTextComponent |
+| literals.rb:68:7:68:11 | "bar" | StringLiteral | 0 | literals.rb:68:8:68:10 | bar | StringTextComponent |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | 0 | literals.rb:69:2:69:5 | foo | StringTextComponent |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | 1 | literals.rb:69:6:69:13 | #{...} | StringInterpolationComponent |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | 0 | literals.rb:70:2:70:5 | foo | StringTextComponent |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | 1 | literals.rb:70:6:70:13 | #{...} | StringInterpolationComponent |
| literals.rb:86:1:86:10 | :"foo bar" | SymbolLiteral | 0 | literals.rb:86:3:86:9 | foo bar | StringTextComponent |
| literals.rb:87:1:87:10 | :"bar baz" | SymbolLiteral | 0 | literals.rb:87:3:87:9 | bar baz | StringTextComponent |
| literals.rb:88:8:88:12 | "bar" | StringLiteral | 0 | literals.rb:88:9:88:11 | bar | StringTextComponent |
| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | 0 | literals.rb:89:4:89:9 | wibble | StringTextComponent |
| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | 0 | literals.rb:90:4:90:16 | wibble wobble | StringTextComponent |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | 0 | literals.rb:91:3:91:6 | foo_ | StringTextComponent |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | 1 | literals.rb:91:7:91:15 | #{...} | StringInterpolationComponent |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | 0 | literals.rb:92:3:92:16 | foo_#{ 1 + 1 } | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 0 | literals.rb:91:3:91:6 | foo_ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 1 | literals.rb:91:7:91:15 | #{...} | StringInterpolationComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 2 | literals.rb:91:16:91:16 | _ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 3 | literals.rb:91:17:91:22 | #{...} | StringInterpolationComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 4 | literals.rb:91:23:91:23 | _ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 5 | literals.rb:91:24:91:29 | #{...} | StringInterpolationComponent |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | SymbolLiteral | 0 | literals.rb:92:3:92:29 | foo_#{ 2 + 2}_#{bar}_#{BAR} | StringTextComponent |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | 0 | literals.rb:93:4:93:17 | foo_#{ 3 - 2 } | StringTextComponent |
| literals.rb:103:4:103:6 | "foo" | StringLiteral | 0 | literals.rb:103:4:103:6 | foo | StringTextComponent |
| literals.rb:103:8:103:10 | "bar" | StringLiteral | 0 | literals.rb:103:8:103:10 | bar | StringTextComponent |
@@ -454,10 +500,14 @@ stringComponents
| literals.rb:105:4:105:6 | "foo" | StringLiteral | 0 | literals.rb:105:4:105:6 | foo | StringTextComponent |
| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | 0 | literals.rb:105:8:105:10 | bar | StringTextComponent |
| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | 1 | literals.rb:105:11:105:16 | #{...} | StringInterpolationComponent |
-| literals.rb:105:18:105:20 | "baz" | StringLiteral | 0 | literals.rb:105:18:105:20 | baz | StringTextComponent |
+| literals.rb:105:18:105:23 | "#{...}" | StringLiteral | 0 | literals.rb:105:18:105:23 | #{...} | StringInterpolationComponent |
+| literals.rb:105:25:105:30 | "#{...}" | StringLiteral | 0 | literals.rb:105:25:105:30 | #{...} | StringInterpolationComponent |
+| literals.rb:105:32:105:34 | "baz" | StringLiteral | 0 | literals.rb:105:32:105:34 | baz | StringTextComponent |
| literals.rb:106:4:106:6 | "foo" | StringLiteral | 0 | literals.rb:106:4:106:6 | foo | StringTextComponent |
| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | 0 | literals.rb:106:8:106:16 | bar#{1+1} | StringTextComponent |
-| literals.rb:106:18:106:20 | "baz" | StringLiteral | 0 | literals.rb:106:18:106:20 | baz | StringTextComponent |
+| literals.rb:106:18:106:23 | "#{bar}" | StringLiteral | 0 | literals.rb:106:18:106:23 | #{bar} | StringTextComponent |
+| literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral | 0 | literals.rb:106:25:106:30 | #{BAR} | StringTextComponent |
+| literals.rb:106:32:106:34 | "baz" | StringLiteral | 0 | literals.rb:106:32:106:34 | baz | StringTextComponent |
| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | 0 | literals.rb:110:4:110:6 | foo | StringTextComponent |
| literals.rb:110:8:110:10 | :"bar" | SymbolLiteral | 0 | literals.rb:110:8:110:10 | bar | StringTextComponent |
| literals.rb:110:12:110:14 | :"baz" | SymbolLiteral | 0 | literals.rb:110:12:110:14 | baz | StringTextComponent |
@@ -467,19 +517,27 @@ stringComponents
| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | 0 | literals.rb:112:4:112:6 | foo | StringTextComponent |
| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | 0 | literals.rb:112:8:112:10 | bar | StringTextComponent |
| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | 1 | literals.rb:112:11:112:20 | #{...} | StringInterpolationComponent |
-| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | 0 | literals.rb:112:22:112:24 | baz | StringTextComponent |
+| literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral | 0 | literals.rb:112:22:112:27 | #{...} | StringInterpolationComponent |
+| literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral | 0 | literals.rb:112:29:112:34 | #{...} | StringInterpolationComponent |
+| literals.rb:112:36:112:38 | :"baz" | SymbolLiteral | 0 | literals.rb:112:36:112:38 | baz | StringTextComponent |
| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | 0 | literals.rb:113:4:113:6 | foo | StringTextComponent |
| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | 0 | literals.rb:113:8:113:12 | bar#{ | StringTextComponent |
| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 0 | literals.rb:113:14:113:14 | 2 | StringTextComponent |
| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | 0 | literals.rb:113:16:113:16 | + | StringTextComponent |
| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 0 | literals.rb:113:18:113:18 | 4 | StringTextComponent |
| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | 0 | literals.rb:113:20:113:20 | } | StringTextComponent |
-| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | 0 | literals.rb:113:22:113:24 | baz | StringTextComponent |
+| literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral | 0 | literals.rb:113:22:113:27 | #{bar} | StringTextComponent |
+| literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral | 0 | literals.rb:113:29:113:34 | #{BAR} | StringTextComponent |
+| literals.rb:113:36:113:38 | :"baz" | SymbolLiteral | 0 | literals.rb:113:36:113:38 | baz | StringTextComponent |
| literals.rb:117:22:117:26 | "baz" | StringLiteral | 0 | literals.rb:117:23:117:25 | baz | StringTextComponent |
| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | 0 | literals.rb:130:2:130:6 | ls -l | StringTextComponent |
| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | 0 | literals.rb:131:4:131:8 | ls -l | StringTextComponent |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:132:2:132:7 | du -d | StringTextComponent |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:132:8:132:17 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 0 | literals.rb:132:2:132:7 | du -d | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 1 | literals.rb:132:8:132:17 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 2 | literals.rb:132:18:132:18 | | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 3 | literals.rb:132:19:132:24 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 4 | literals.rb:132:25:132:25 | | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 5 | literals.rb:132:26:132:31 | #{...} | StringInterpolationComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:133:4:133:9 | du -d | StringTextComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:133:10:133:19 | #{...} | StringInterpolationComponent |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
@@ -488,9 +546,11 @@ stringComponents
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | StringEscapeSequenceComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | StringTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | StringInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | StringInterpolationComponent |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | StringTextComponent |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | StringTextComponent |
@@ -498,9 +558,11 @@ stringComponents
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | StringEscapeSequenceComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | StringTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | StringInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | StringInterpolationComponent |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | StringTextComponent |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:150:2:150:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:151:2:151:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
@@ -536,13 +598,27 @@ stringInterpolations
| literals.rb:65:14:65:23 | #{...} | 0 | literals.rb:65:17:65:21 | ... + ... | AddExpr |
| literals.rb:66:6:66:21 | #{...} | 0 | literals.rb:66:9:66:14 | call to blah | MethodCall |
| literals.rb:66:6:66:21 | #{...} | 1 | literals.rb:66:17:66:19 | ... + ... | AddExpr |
+| literals.rb:69:6:69:13 | #{...} | 0 | literals.rb:69:9:69:11 | bar | LocalVariableAccess |
+| literals.rb:70:6:70:13 | #{...} | 0 | literals.rb:70:9:70:11 | BAR | ConstantReadAccess |
| literals.rb:91:7:91:15 | #{...} | 0 | literals.rb:91:10:91:14 | ... + ... | AddExpr |
+| literals.rb:91:17:91:22 | #{...} | 0 | literals.rb:91:19:91:21 | bar | LocalVariableAccess |
+| literals.rb:91:24:91:29 | #{...} | 0 | literals.rb:91:26:91:28 | BAR | ConstantReadAccess |
| literals.rb:105:11:105:16 | #{...} | 0 | literals.rb:105:13:105:15 | ... + ... | AddExpr |
+| literals.rb:105:18:105:23 | #{...} | 0 | literals.rb:105:20:105:22 | bar | LocalVariableAccess |
+| literals.rb:105:25:105:30 | #{...} | 0 | literals.rb:105:27:105:29 | BAR | ConstantReadAccess |
| literals.rb:112:11:112:20 | #{...} | 0 | literals.rb:112:14:112:18 | ... + ... | AddExpr |
+| literals.rb:112:22:112:27 | #{...} | 0 | literals.rb:112:24:112:26 | bar | LocalVariableAccess |
+| literals.rb:112:29:112:34 | #{...} | 0 | literals.rb:112:31:112:33 | BAR | ConstantReadAccess |
| literals.rb:132:8:132:17 | #{...} | 0 | literals.rb:132:11:132:15 | ... + ... | AddExpr |
+| literals.rb:132:19:132:24 | #{...} | 0 | literals.rb:132:21:132:23 | bar | LocalVariableAccess |
+| literals.rb:132:26:132:31 | #{...} | 0 | literals.rb:132:28:132:30 | BAR | ConstantReadAccess |
| literals.rb:133:10:133:19 | #{...} | 0 | literals.rb:133:13:133:17 | ... - ... | SubExpr |
| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
+| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
+| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
+| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
+| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
| literals.rb:158:14:158:22 | #{...} | 0 | literals.rb:158:17:158:20 | call to name | MethodCall |
| literals.rb:172:12:172:29 | #{...} | 0 | literals.rb:172:15:172:27 | call to interpolation | MethodCall |
| literals.rb:177:15:177:32 | #{...} | 0 | literals.rb:177:18:177:30 | call to interpolation | MethodCall |
@@ -553,9 +629,9 @@ concatenatedStrings
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 0 | literals.rb:63:1:63:7 | "foo" |
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 1 | literals.rb:63:9:63:13 | "bar" |
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 2 | literals.rb:63:15:63:19 | "baz" |
-| literals.rb:64:1:64:27 | "..." "..." | | 0 | literals.rb:64:1:64:5 | "foo" |
-| literals.rb:64:1:64:27 | "..." "..." | | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
-| literals.rb:64:1:64:27 | "..." "..." | | 2 | literals.rb:64:23:64:27 | "baz" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 0 | literals.rb:64:1:64:5 | "foo" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 2 | literals.rb:64:23:64:27 | "baz" |
arrayLiterals
| literals.rb:96:1:96:2 | [...] | 0 |
| literals.rb:97:1:97:9 | [...] | 3 |
@@ -565,13 +641,13 @@ arrayLiterals
| literals.rb:102:1:102:4 | %w(...) | 0 |
| literals.rb:103:1:103:15 | %w(...) | 3 |
| literals.rb:104:1:104:15 | %w(...) | 3 |
-| literals.rb:105:1:105:21 | %w(...) | 3 |
-| literals.rb:106:1:106:21 | %w(...) | 3 |
+| literals.rb:105:1:105:35 | %w(...) | 5 |
+| literals.rb:106:1:106:35 | %w(...) | 5 |
| literals.rb:109:1:109:4 | %i(...) | 0 |
| literals.rb:110:1:110:15 | %i(...) | 3 |
| literals.rb:111:1:111:15 | %i(...) | 3 |
-| literals.rb:112:1:112:25 | %i(...) | 3 |
-| literals.rb:113:1:113:25 | %i(...) | 7 |
+| literals.rb:112:1:112:39 | %i(...) | 5 |
+| literals.rb:113:1:113:39 | %i(...) | 9 |
arrayLiteralElements
| literals.rb:97:1:97:9 | [...] | 0 | literals.rb:97:2:97:2 | 1 | IntegerLiteral |
| literals.rb:97:1:97:9 | [...] | 1 | literals.rb:97:5:97:5 | 2 | IntegerLiteral |
@@ -589,28 +665,36 @@ arrayLiteralElements
| literals.rb:104:1:104:15 | %w(...) | 0 | literals.rb:104:4:104:6 | "foo" | StringLiteral |
| literals.rb:104:1:104:15 | %w(...) | 1 | literals.rb:104:8:104:10 | "bar" | StringLiteral |
| literals.rb:104:1:104:15 | %w(...) | 2 | literals.rb:104:12:104:14 | "baz" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 2 | literals.rb:105:18:105:20 | "baz" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 2 | literals.rb:106:18:106:20 | "baz" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 2 | literals.rb:105:18:105:23 | "#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 3 | literals.rb:105:25:105:30 | "#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 4 | literals.rb:105:32:105:34 | "baz" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 2 | literals.rb:106:18:106:23 | "#{bar}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 3 | literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 4 | literals.rb:106:32:106:34 | "baz" | StringLiteral |
| literals.rb:110:1:110:15 | %i(...) | 0 | literals.rb:110:4:110:6 | :"foo" | SymbolLiteral |
| literals.rb:110:1:110:15 | %i(...) | 1 | literals.rb:110:8:110:10 | :"bar" | SymbolLiteral |
| literals.rb:110:1:110:15 | %i(...) | 2 | literals.rb:110:12:110:14 | :"baz" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 0 | literals.rb:111:4:111:6 | :"foo" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 1 | literals.rb:111:8:111:10 | :"bar" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 2 | literals.rb:111:12:111:14 | :"baz" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 2 | literals.rb:112:22:112:24 | :"baz" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 6 | literals.rb:113:22:113:24 | :"baz" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 2 | literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 3 | literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 4 | literals.rb:112:36:112:38 | :"baz" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 6 | literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 7 | literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 8 | literals.rb:113:36:113:38 | :"baz" | SymbolLiteral |
hashLiterals
| literals.rb:88:1:88:14 | {...} | 1 |
| literals.rb:116:1:116:2 | {...} | 0 |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.rb b/ruby/ql/test/library-tests/ast/literals/literals.rb
index 1c1304d9eef..3918bfc1186 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.rb
+++ b/ruby/ql/test/library-tests/ast/literals/literals.rb
@@ -64,10 +64,10 @@ TRUE
"foo" "bar#{ 1 * 1 }" 'baz' # concatenated, interpolation
"foo #{ "bar #{ 2 + 3 } baz" } qux" # interpolation containing string containing interpolation
"foo #{ blah(); 1+9 }" # multiple statements in interpolation
-
-
-
-
+bar = "bar"
+BAR = "bar"
+"foo #{ bar }" # local variables in interpolation
+"foo #{ BAR }" # constants in interpolation
# characters
?x
@@ -88,8 +88,8 @@ TRUE
{ foo: "bar" }
%s(wibble)
%s[wibble wobble]
-:"foo_#{ 2 + 2}" # interpolation
-:'foo_#{ 1 + 1 }' # no interpolation
+:"foo_#{ 2 + 2}_#{bar}_#{BAR}" # interpolation
+:'foo_#{ 2 + 2}_#{bar}_#{BAR}' # no interpolation
%s(foo_#{ 3 - 2 }) # no interpolation
# arrays
@@ -102,20 +102,20 @@ TRUE
%w()
%w(foo bar baz)
%w!foo bar baz!
-%W[foo bar#{1+1} baz] # interpolation
-%w[foo bar#{1+1} baz] # no interpolation
+%W[foo bar#{1+1} #{bar} #{BAR} baz] # interpolation
+%w[foo bar#{1+1} #{bar} #{BAR} baz] # no interpolation
# arrays of symbols
%i()
%i(foo bar baz)
%i@foo bar baz@
-%I(foo bar#{ 2 + 4 } baz) # interpolation
-%i(foo bar#{ 2 + 4 } baz) # no interpolation
+%I(foo bar#{ 2 + 4 } #{bar} #{BAR} baz) # interpolation
+%i(foo bar#{ 2 + 4 } #{bar} #{BAR} baz) # no interpolation
# hashes
{}
{ foo: 1, :bar => 2, 'baz' => 3 }
-{ foo: 7, **bar } # hash-splat argument
+{ foo: 7, **baz } # hash-splat argument
# ranges
(1..10)
@@ -129,21 +129,21 @@ TRUE
# subshell
`ls -l`
%x(ls -l)
-`du -d #{ 1 + 1 }` # interpolation
-%x@du -d #{ 5 - 4 }@ # interpolation
+`du -d #{ 1 + 1 } #{bar} #{BAR}` # interpolation
+%x@du -d #{ 5 - 4 }@ # interpolation
# regular expressions
//
/foo/
/foo/i
/foo+\sbar\S/
-/foo#{ 1 + 1 }bar/ # interpolation
+/foo#{ 1 + 1 }bar#{bar}#{BAR}/ # interpolation
/foo/oxm
%r[]
%r(foo)
%r:foo:i
%r{foo+\sbar\S}
-%r{foo#{ 1 + 1 }bar} # interpolation
+%r{foo#{ 1 + 1 }bar#{bar}#{BAR}} # interpolation
%r:foo:mxo
# long strings
diff --git a/ruby/ql/test/library-tests/ast/misc/misc.expected b/ruby/ql/test/library-tests/ast/misc/misc.expected
index 45235cd5787..befd5734091 100644
--- a/ruby/ql/test/library-tests/ast/misc/misc.expected
+++ b/ruby/ql/test/library-tests/ast/misc/misc.expected
@@ -4,7 +4,7 @@ undef
| misc.rb:3:1:3:30 | undef ... | 2 | misc.rb:3:18:3:21 | foo= | foo= | MethodName |
| misc.rb:3:1:3:30 | undef ... | 3 | misc.rb:3:24:3:25 | [] | [] | MethodName |
| misc.rb:3:1:3:30 | undef ... | 4 | misc.rb:3:28:3:30 | []= | []= | MethodName |
-| misc.rb:4:1:4:19 | undef ... | 0 | misc.rb:4:7:4:19 | :"foo_#{...}" | (none) | MethodName |
+| misc.rb:4:1:4:19 | undef ... | 0 | misc.rb:4:7:4:19 | :"foo_#{...}" | foo_bar | MethodName |
| misc.rb:5:1:5:35 | undef ... | 0 | misc.rb:5:7:5:9 | nil | nil | MethodName |
| misc.rb:5:1:5:35 | undef ... | 1 | misc.rb:5:12:5:15 | true | true | MethodName |
| misc.rb:5:1:5:35 | undef ... | 2 | misc.rb:5:18:5:22 | false | false | MethodName |
@@ -17,5 +17,5 @@ alias
| misc.rb:8:1:8:14 | alias ... | old | misc.rb:8:12:8:14 | []= | []= | MethodName |
| misc.rb:9:1:9:16 | alias ... | new | misc.rb:9:7:9:11 | super | super | MethodName |
| misc.rb:9:1:9:16 | alias ... | old | misc.rb:9:13:9:16 | self | self | MethodName |
-| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | (none) | MethodName |
+| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | \\nbar | MethodName |
| misc.rb:10:1:10:24 | alias ... | old | misc.rb:10:19:10:24 | :"foo" | foo | MethodName |
diff --git a/ruby/ql/test/library-tests/regexp/parse.expected b/ruby/ql/test/library-tests/regexp/parse.expected
index af5c9135ee6..756a69e8315 100644
--- a/ruby/ql/test/library-tests/regexp/parse.expected
+++ b/ruby/ql/test/library-tests/regexp/parse.expected
@@ -582,3 +582,14 @@ regexp.rb:
# 71| [RegExpConstant, RegExpNormalChar] f
# 74| [RegExpNamedCharacterProperty] [:digit:]
+
+# 78| [RegExpConstant, RegExpNormalChar] a
+
+# 78| [RegExpSequence] abc
+#-----| 0 -> [RegExpConstant, RegExpNormalChar] a
+#-----| 1 -> [RegExpConstant, RegExpNormalChar] b
+#-----| 2 -> [RegExpConstant, RegExpNormalChar] c
+
+# 78| [RegExpConstant, RegExpNormalChar] b
+
+# 78| [RegExpConstant, RegExpNormalChar] c
diff --git a/ruby/ql/test/library-tests/regexp/regexp.rb b/ruby/ql/test/library-tests/regexp/regexp.rb
index c1b94b52370..28030b914e5 100644
--- a/ruby/ql/test/library-tests/regexp/regexp.rb
+++ b/ruby/ql/test/library-tests/regexp/regexp.rb
@@ -71,4 +71,8 @@
/[A-F[:digit:]a-f]/
# *Not* a POSIX bracket expression; just a regular character class.
-/[:digit:]/
\ No newline at end of file
+/[:digit:]/
+
+# Simple constant interpolation
+A = "a"
+/#{A}bc/
\ No newline at end of file
From 23f1352953e9c43f789e1aa356d47c2875479c5d Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 13 Dec 2021 16:21:03 +1300
Subject: [PATCH 013/296] Add ReDoS test that uses string interpolation
This exercises the support for resolving string interpolations, and is
based on a real vulnerability:
https://github.com/advisories/GHSA-jxhc-q857-3j6g)
---
.../cwe-1333-exponential-redos/ReDoS.expected | 1 +
.../addressable-LICENSE | 201 ++++++++++++++++++
.../cwe-1333-exponential-redos/tst.rb | 11 +
3 files changed, 213 insertions(+)
create mode 100644 ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
index 9a3d82b41a0..213f0e11189 100644
--- a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
@@ -94,3 +94,4 @@
| tst.rb:375:11:375:27 | ([[:digit:]]\|\\d)+ | This part of the regular expression may cause exponential backtracking on strings starting with 'X' and containing many repetitions of '0'. |
| tst.rb:378:12:378:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
| tst.rb:379:12:379:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
+| tst.rb:390:66:390:67 | .? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '00\\\\'. |
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
new file mode 100644
index 00000000000..11069edd790
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
index 0d4e893c660..19d22033c10 100644
--- a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
@@ -378,3 +378,14 @@ bad88 = /X([[:digit:]]|\d)+Y/
bad89 = /\G(a|\w)*$/
bad90 = /\b(a|\w)*$/
+# NOT GOOD; attack: "0".repeat(30) + "!"
+# Adapated from addressable (https://github.com/sporkmonger/addressable)
+# which is licensed under the Apache License 2.0; see file addressable-LICENSE.
+module Bad91
+ ALPHA = "a-zA-Z"
+ DIGIT = "0-9"
+ var_char_class = ALPHA + DIGIT + '_'
+ var_char = "(?:(?:[#{var_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
+ var = "(?:#{var_char}(?:\\.?#{var_char})*)"
+ bad91 = /^#{var}$/
+end
From 301d0bbdf81096f1f0988f01fb72973bc9147f2c Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 10:44:24 +0100
Subject: [PATCH 014/296] Ruby: Restructure test to avoid dead code
---
ruby/ql/test/library-tests/ast/Ast.expected | 275 +++++++++---------
.../library-tests/ast/AstDesugar.expected | 20 +-
.../test/library-tests/ast/ValueText.expected | 77 ++---
.../ast/control/CaseExpr.expected | 98 ++++---
.../ast/control/ControlExpr.expected | 9 +-
.../test/library-tests/ast/control/cases.rb | 7 +-
6 files changed, 248 insertions(+), 238 deletions(-)
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 57c9704bc40..94b5cb5fda1 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -920,187 +920,190 @@ control/cases.rb:
# 88| getPattern: [VariableReferencePattern] ^...
# 88| getVariableAccess: [LocalVariableAccess] foo
# 89| getBranch: [InClause] in ... then ...
-# 89| getPattern: [LocalVariableAccess] var
+# 89| getPattern: [StringLiteral] "string"
+# 89| getComponent: [StringTextComponent] string
# 90| getBranch: [InClause] in ... then ...
-# 90| getPattern: [StringLiteral] "string"
-# 90| getComponent: [StringTextComponent] string
+# 90| getPattern: [ArrayLiteral] %w(...)
+# 90| getElement: [StringLiteral] "foo"
+# 90| getComponent: [StringTextComponent] foo
+# 90| getElement: [StringLiteral] "bar"
+# 90| getComponent: [StringTextComponent] bar
# 91| getBranch: [InClause] in ... then ...
-# 91| getPattern: [ArrayLiteral] %w(...)
-# 91| getElement: [StringLiteral] "foo"
+# 91| getPattern: [ArrayLiteral] %i(...)
+# 91| getElement: [SymbolLiteral] :"foo"
# 91| getComponent: [StringTextComponent] foo
-# 91| getElement: [StringLiteral] "bar"
+# 91| getElement: [SymbolLiteral] :"bar"
# 91| getComponent: [StringTextComponent] bar
# 92| getBranch: [InClause] in ... then ...
-# 92| getPattern: [ArrayLiteral] %i(...)
-# 92| getElement: [SymbolLiteral] :"foo"
-# 92| getComponent: [StringTextComponent] foo
-# 92| getElement: [SymbolLiteral] :"bar"
-# 92| getComponent: [StringTextComponent] bar
+# 92| getPattern: [RegExpLiteral] /.*abc[0-9]/
+# 92| getParsed: [RegExpSequence] .*abc[0-9]
+# 92| 0: [RegExpStar] .*
+# 92| 0: [RegExpDot] .
+# 92| 1: [RegExpConstant, RegExpNormalChar] a
+# 92| 2: [RegExpConstant, RegExpNormalChar] b
+# 92| 3: [RegExpConstant, RegExpNormalChar] c
+# 92| 4: [RegExpCharacterClass] [0-9]
+# 92| 0: [RegExpCharacterRange] 0-9
+# 92| 0: [RegExpConstant, RegExpNormalChar] 0
+# 92| 1: [RegExpConstant, RegExpNormalChar] 9
+# 92| getComponent: [StringTextComponent] .*abc[0-9]
# 93| getBranch: [InClause] in ... then ...
-# 93| getPattern: [RegExpLiteral] /.*abc[0-9]/
-# 93| getParsed: [RegExpSequence] .*abc[0-9]
-# 93| 0: [RegExpStar] .*
-# 93| 0: [RegExpDot] .
-# 93| 1: [RegExpConstant, RegExpNormalChar] a
-# 93| 2: [RegExpConstant, RegExpNormalChar] b
-# 93| 3: [RegExpConstant, RegExpNormalChar] c
-# 93| 4: [RegExpCharacterClass] [0-9]
-# 93| 0: [RegExpCharacterRange] 0-9
-# 93| 0: [RegExpConstant, RegExpNormalChar] 0
-# 93| 1: [RegExpConstant, RegExpNormalChar] 9
-# 93| getComponent: [StringTextComponent] .*abc[0-9]
+# 93| getPattern: [RangeLiteral] _ .. _
+# 93| getBegin: [IntegerLiteral] 5
+# 93| getEnd: [IntegerLiteral] 10
# 94| getBranch: [InClause] in ... then ...
# 94| getPattern: [RangeLiteral] _ .. _
-# 94| getBegin: [IntegerLiteral] 5
# 94| getEnd: [IntegerLiteral] 10
# 95| getBranch: [InClause] in ... then ...
# 95| getPattern: [RangeLiteral] _ .. _
-# 95| getEnd: [IntegerLiteral] 10
+# 95| getBegin: [IntegerLiteral] 5
# 96| getBranch: [InClause] in ... then ...
-# 96| getPattern: [RangeLiteral] _ .. _
-# 96| getBegin: [IntegerLiteral] 5
+# 96| getPattern: [AsPattern] ... => ...
+# 96| getPattern: [IntegerLiteral] 5
+# 96| getVariableAccess: [LocalVariableAccess] x
# 97| getBranch: [InClause] in ... then ...
-# 97| getPattern: [AsPattern] ... => ...
-# 97| getPattern: [IntegerLiteral] 5
-# 97| getVariableAccess: [LocalVariableAccess] x
+# 97| getPattern: [ConstantReadAccess] Foo
# 98| getBranch: [InClause] in ... then ...
-# 98| getPattern: [AlternativePattern] ... | ...
-# 98| getAlternative: [IntegerLiteral] 5
-# 98| getAlternative: [VariableReferencePattern] ^...
-# 98| getVariableAccess: [LocalVariableAccess] foo
-# 98| getAlternative: [LocalVariableAccess] var
-# 98| getAlternative: [StringLiteral] "string"
-# 98| getComponent: [StringTextComponent] string
+# 98| getPattern: [ConstantReadAccess] Bar
+# 98| getScopeExpr: [ConstantReadAccess] Foo
# 99| getBranch: [InClause] in ... then ...
-# 99| getPattern: [ConstantReadAccess] Foo
+# 99| getPattern: [ConstantReadAccess] Bar
+# 99| getScopeExpr: [ConstantReadAccess] Foo
# 100| getBranch: [InClause] in ... then ...
-# 100| getPattern: [ConstantReadAccess] Bar
-# 100| getScopeExpr: [ConstantReadAccess] Foo
+# 100| getPattern: [AlternativePattern] ... | ...
+# 100| getAlternative: [NilLiteral] nil
+# 100| getAlternative: [Self, SelfVariableAccess] self
+# 100| getAlternative: [BooleanLiteral] true
+# 100| getAlternative: [BooleanLiteral] false
+# 100| getAlternative: [LineLiteral] __LINE__
+# 100| getAlternative: [FileLiteral] __FILE__
+# 100| getAlternative: [EncodingLiteral] __ENCODING__
# 101| getBranch: [InClause] in ... then ...
-# 101| getPattern: [ConstantReadAccess] Bar
-# 101| getScopeExpr: [ConstantReadAccess] Foo
+# 101| getPattern: [Lambda] -> { ... }
+# 101| getParameter: [SimpleParameter] x
+# 101| getDefiningAccess: [LocalVariableAccess] x
+# 101| getStmt: [EqExpr] ... == ...
+# 101| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
+# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 10
# 102| getBranch: [InClause] in ... then ...
-# 102| getPattern: [AlternativePattern] ... | ...
-# 102| getAlternative: [NilLiteral] nil
-# 102| getAlternative: [Self, SelfVariableAccess] self
-# 102| getAlternative: [BooleanLiteral] true
-# 102| getAlternative: [BooleanLiteral] false
-# 102| getAlternative: [LineLiteral] __LINE__
-# 102| getAlternative: [FileLiteral] __FILE__
-# 102| getAlternative: [EncodingLiteral] __ENCODING__
+# 102| getPattern: [SymbolLiteral] :foo
# 103| getBranch: [InClause] in ... then ...
-# 103| getPattern: [Lambda] -> { ... }
-# 103| getParameter: [SimpleParameter] x
-# 103| getDefiningAccess: [LocalVariableAccess] x
-# 103| getStmt: [EqExpr] ... == ...
-# 103| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
-# 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 10
+# 103| getPattern: [SymbolLiteral] :"foo bar"
+# 103| getComponent: [StringTextComponent] foo bar
# 104| getBranch: [InClause] in ... then ...
-# 104| getPattern: [SymbolLiteral] :foo
+# 104| getPattern: [AlternativePattern] ... | ...
+# 104| getAlternative: [UnaryMinusExpr] - ...
+# 104| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 5
+# 104| getAlternative: [UnaryPlusExpr] + ...
+# 104| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 10
# 105| getBranch: [InClause] in ... then ...
-# 105| getPattern: [SymbolLiteral] :"foo bar"
-# 105| getComponent: [StringTextComponent] foo bar
+# 105| getPattern: [ParenthesizedPattern] ( ... )
+# 105| getPattern: [RangeLiteral] _ .. _
+# 105| getBegin: [IntegerLiteral] 1
# 106| getBranch: [InClause] in ... then ...
-# 106| getPattern: [AlternativePattern] ... | ...
-# 106| getAlternative: [UnaryMinusExpr] - ...
-# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 5
-# 106| getAlternative: [UnaryPlusExpr] + ...
-# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 10
+# 106| getPattern: [ParenthesizedPattern] ( ... )
+# 106| getPattern: [AlternativePattern] ... | ...
+# 106| getAlternative: [IntegerLiteral] 0
+# 106| getAlternative: [StringLiteral] ""
+# 106| getAlternative: [ArrayPattern] [ ..., * ]
+# 106| getAlternative: [HashPattern] { ..., ** }
# 107| getBranch: [InClause] in ... then ...
-# 107| getPattern: [ParenthesizedPattern] ( ... )
-# 107| getPattern: [RangeLiteral] _ .. _
-# 107| getBegin: [IntegerLiteral] 1
-# 108| getBranch: [InClause] in ... then ...
-# 108| getPattern: [ParenthesizedPattern] ( ... )
-# 108| getPattern: [AlternativePattern] ... | ...
-# 108| getAlternative: [IntegerLiteral] 0
-# 108| getAlternative: [StringLiteral] ""
-# 108| getAlternative: [ArrayPattern] [ ..., * ]
-# 108| getAlternative: [HashPattern] { ..., ** }
-# 113| getStmt: [CaseExpr] case ...
-# 113| getValue: [MethodCall] call to expr
-# 113| getReceiver: [Self, SelfVariableAccess] self
-# 114| getBranch: [InClause] in ... then ...
-# 114| getPattern: [ArrayPattern] [ ..., * ]
-# 115| getBranch: [InClause] in ... then ...
-# 115| getPattern: [ArrayPattern] [ ..., * ]
-# 115| getPrefixElement: [LocalVariableAccess] x
-# 116| getBranch: [InClause] in ... then ...
-# 116| getPattern: [ArrayPattern] [ ..., * ]
-# 116| getPrefixElement/getSuffixElement: [LocalVariableAccess] x
+# 107| getPattern: [LocalVariableAccess] var
+# 110| getStmt: [CaseExpr] case ...
+# 110| getValue: [MethodCall] call to expr
+# 110| getReceiver: [Self, SelfVariableAccess] self
+# 111| getBranch: [InClause] in ... then ...
+# 111| getPattern: [AlternativePattern] ... | ...
+# 111| getAlternative: [IntegerLiteral] 5
+# 111| getAlternative: [VariableReferencePattern] ^...
+# 111| getVariableAccess: [LocalVariableAccess] foo
+# 111| getAlternative: [StringLiteral] "string"
+# 111| getComponent: [StringTextComponent] string
+# 111| getAlternative: [LocalVariableAccess] var
+# 116| getStmt: [CaseExpr] case ...
+# 116| getValue: [MethodCall] call to expr
+# 116| getReceiver: [Self, SelfVariableAccess] self
# 117| getBranch: [InClause] in ... then ...
# 117| getPattern: [ArrayPattern] [ ..., * ]
-# 117| getClass: [ConstantReadAccess] Bar
-# 117| getScopeExpr: [ConstantReadAccess] Foo
# 118| getBranch: [InClause] in ... then ...
# 118| getPattern: [ArrayPattern] [ ..., * ]
-# 118| getClass: [ConstantReadAccess] Foo
+# 118| getPrefixElement: [LocalVariableAccess] x
# 119| getBranch: [InClause] in ... then ...
# 119| getPattern: [ArrayPattern] [ ..., * ]
-# 119| getClass: [ConstantReadAccess] Bar
+# 119| getPrefixElement/getSuffixElement: [LocalVariableAccess] x
# 120| getBranch: [InClause] in ... then ...
# 120| getPattern: [ArrayPattern] [ ..., * ]
# 120| getClass: [ConstantReadAccess] Bar
-# 120| getPrefixElement/getSuffixElement: [LocalVariableAccess] a
-# 120| getPrefixElement/getSuffixElement: [LocalVariableAccess] b
-# 120| getRestVariableAccess: [LocalVariableAccess] c
-# 120| getSuffixElement: [LocalVariableAccess] d
-# 120| getSuffixElement: [LocalVariableAccess] e
-# 125| getStmt: [CaseExpr] case ...
-# 125| getValue: [MethodCall] call to expr
-# 125| getReceiver: [Self, SelfVariableAccess] self
-# 126| getBranch: [InClause] in ... then ...
-# 126| getPattern: [FindPattern] [ *,...,* ]
-# 126| getElement: [LocalVariableAccess] x
-# 127| getBranch: [InClause] in ... then ...
-# 127| getPattern: [FindPattern] [ *,...,* ]
-# 127| getPrefixVariableAccess: [LocalVariableAccess] x
-# 127| getElement: [IntegerLiteral] 1
-# 127| getElement: [IntegerLiteral] 2
-# 127| getSuffixVariableAccess: [LocalVariableAccess] y
-# 128| getBranch: [InClause] in ... then ...
-# 128| getPattern: [FindPattern] [ *,...,* ]
-# 128| getClass: [ConstantReadAccess] Bar
-# 128| getScopeExpr: [ConstantReadAccess] Foo
-# 128| getElement: [IntegerLiteral] 1
+# 120| getScopeExpr: [ConstantReadAccess] Foo
+# 121| getBranch: [InClause] in ... then ...
+# 121| getPattern: [ArrayPattern] [ ..., * ]
+# 121| getClass: [ConstantReadAccess] Foo
+# 122| getBranch: [InClause] in ... then ...
+# 122| getPattern: [ArrayPattern] [ ..., * ]
+# 122| getClass: [ConstantReadAccess] Bar
+# 123| getBranch: [InClause] in ... then ...
+# 123| getPattern: [ArrayPattern] [ ..., * ]
+# 123| getClass: [ConstantReadAccess] Bar
+# 123| getPrefixElement/getSuffixElement: [LocalVariableAccess] a
+# 123| getPrefixElement/getSuffixElement: [LocalVariableAccess] b
+# 123| getRestVariableAccess: [LocalVariableAccess] c
+# 123| getSuffixElement: [LocalVariableAccess] d
+# 123| getSuffixElement: [LocalVariableAccess] e
+# 128| getStmt: [CaseExpr] case ...
+# 128| getValue: [MethodCall] call to expr
+# 128| getReceiver: [Self, SelfVariableAccess] self
# 129| getBranch: [InClause] in ... then ...
# 129| getPattern: [FindPattern] [ *,...,* ]
-# 129| getClass: [ConstantReadAccess] Foo
-# 129| getElement: [ConstantReadAccess] Bar
-# 134| getStmt: [CaseExpr] case ...
-# 134| getValue: [MethodCall] call to expr
-# 134| getReceiver: [Self, SelfVariableAccess] self
-# 135| getBranch: [InClause] in ... then ...
-# 135| getPattern: [HashPattern] { ..., ** }
-# 136| getBranch: [InClause] in ... then ...
-# 136| getPattern: [HashPattern] { ..., ** }
-# 136| getKey: [SymbolLiteral] :x
-# 137| getBranch: [InClause] in ... then ...
-# 137| getPattern: [HashPattern] { ..., ** }
-# 137| getClass: [ConstantReadAccess] Bar
-# 137| getScopeExpr: [ConstantReadAccess] Foo
-# 137| getKey: [SymbolLiteral] :x
-# 137| getValue: [IntegerLiteral] 1
+# 129| getElement: [LocalVariableAccess] x
+# 130| getBranch: [InClause] in ... then ...
+# 130| getPattern: [FindPattern] [ *,...,* ]
+# 130| getPrefixVariableAccess: [LocalVariableAccess] x
+# 130| getElement: [IntegerLiteral] 1
+# 130| getElement: [IntegerLiteral] 2
+# 130| getSuffixVariableAccess: [LocalVariableAccess] y
+# 131| getBranch: [InClause] in ... then ...
+# 131| getPattern: [FindPattern] [ *,...,* ]
+# 131| getClass: [ConstantReadAccess] Bar
+# 131| getScopeExpr: [ConstantReadAccess] Foo
+# 131| getElement: [IntegerLiteral] 1
+# 132| getBranch: [InClause] in ... then ...
+# 132| getPattern: [FindPattern] [ *,...,* ]
+# 132| getClass: [ConstantReadAccess] Foo
+# 132| getElement: [ConstantReadAccess] Bar
+# 137| getStmt: [CaseExpr] case ...
+# 137| getValue: [MethodCall] call to expr
+# 137| getReceiver: [Self, SelfVariableAccess] self
# 138| getBranch: [InClause] in ... then ...
# 138| getPattern: [HashPattern] { ..., ** }
-# 138| getClass: [ConstantReadAccess] Bar
-# 138| getScopeExpr: [ConstantReadAccess] Foo
-# 138| getKey: [SymbolLiteral] :x
-# 138| getValue: [IntegerLiteral] 1
-# 138| getKey: [SymbolLiteral] :a
-# 138| getRestVariableAccess: [LocalVariableAccess] rest
# 139| getBranch: [InClause] in ... then ...
# 139| getPattern: [HashPattern] { ..., ** }
-# 139| getClass: [ConstantReadAccess] Foo
-# 139| getKey: [SymbolLiteral] :y
+# 139| getKey: [SymbolLiteral] :x
# 140| getBranch: [InClause] in ... then ...
# 140| getPattern: [HashPattern] { ..., ** }
# 140| getClass: [ConstantReadAccess] Bar
+# 140| getScopeExpr: [ConstantReadAccess] Foo
+# 140| getKey: [SymbolLiteral] :x
+# 140| getValue: [IntegerLiteral] 1
# 141| getBranch: [InClause] in ... then ...
# 141| getPattern: [HashPattern] { ..., ** }
# 141| getClass: [ConstantReadAccess] Bar
-# 141| getKey: [SymbolLiteral] :a
+# 141| getScopeExpr: [ConstantReadAccess] Foo
+# 141| getKey: [SymbolLiteral] :x
# 141| getValue: [IntegerLiteral] 1
+# 141| getKey: [SymbolLiteral] :a
+# 141| getRestVariableAccess: [LocalVariableAccess] rest
+# 142| getBranch: [InClause] in ... then ...
+# 142| getPattern: [HashPattern] { ..., ** }
+# 142| getClass: [ConstantReadAccess] Foo
+# 142| getKey: [SymbolLiteral] :y
+# 143| getBranch: [InClause] in ... then ...
+# 143| getPattern: [HashPattern] { ..., ** }
+# 143| getClass: [ConstantReadAccess] Bar
+# 144| getBranch: [InClause] in ... then ...
+# 144| getPattern: [HashPattern] { ..., ** }
+# 144| getClass: [ConstantReadAccess] Bar
+# 144| getKey: [SymbolLiteral] :a
+# 144| getValue: [IntegerLiteral] 1
modules/classes.rb:
# 2| [Toplevel] classes.rb
# 3| getStmt: [ClassDeclaration] Foo
diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected
index 6acafd116c5..4bc31acf32b 100644
--- a/ruby/ql/test/library-tests/ast/AstDesugar.expected
+++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected
@@ -267,20 +267,20 @@ calls/calls.rb:
# 340| getArgument: [IntegerLiteral] 5
# 340| getArgument: [IntegerLiteral] 6
control/cases.rb:
-# 91| [ArrayLiteral] %w(...)
+# 90| [ArrayLiteral] %w(...)
+# 90| getDesugared: [MethodCall] call to []
+# 90| getReceiver: [ConstantReadAccess] Array
+# 90| getArgument: [StringLiteral] "foo"
+# 90| getComponent: [StringTextComponent] foo
+# 90| getArgument: [StringLiteral] "bar"
+# 90| getComponent: [StringTextComponent] bar
+# 91| [ArrayLiteral] %i(...)
# 91| getDesugared: [MethodCall] call to []
# 91| getReceiver: [ConstantReadAccess] Array
-# 91| getArgument: [StringLiteral] "foo"
+# 91| getArgument: [SymbolLiteral] :"foo"
# 91| getComponent: [StringTextComponent] foo
-# 91| getArgument: [StringLiteral] "bar"
+# 91| getArgument: [SymbolLiteral] :"bar"
# 91| getComponent: [StringTextComponent] bar
-# 92| [ArrayLiteral] %i(...)
-# 92| getDesugared: [MethodCall] call to []
-# 92| getReceiver: [ConstantReadAccess] Array
-# 92| getArgument: [SymbolLiteral] :"foo"
-# 92| getComponent: [StringTextComponent] foo
-# 92| getArgument: [SymbolLiteral] :"bar"
-# 92| getComponent: [StringTextComponent] bar
constants/constants.rb:
# 20| [ArrayLiteral] [...]
# 20| getDesugared: [MethodCall] call to []
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index e2a318c333c..57167453e7b 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -194,45 +194,46 @@
| control/cases.rb:84:7:84:8 | 42 | 42 |
| control/cases.rb:87:6:87:6 | 5 | 5 |
| control/cases.rb:88:7:88:9 | foo | 42 |
-| control/cases.rb:90:6:90:13 | "string" | string |
-| control/cases.rb:91:9:91:11 | "foo" | foo |
-| control/cases.rb:91:13:91:15 | "bar" | bar |
-| control/cases.rb:92:9:92:11 | :"foo" | foo |
-| control/cases.rb:92:13:92:15 | :"bar" | bar |
-| control/cases.rb:93:6:93:17 | /.*abc[0-9]/ | .*abc[0-9] |
-| control/cases.rb:94:6:94:6 | 5 | 5 |
-| control/cases.rb:94:11:94:12 | 10 | 10 |
-| control/cases.rb:95:9:95:10 | 10 | 10 |
+| control/cases.rb:89:6:89:13 | "string" | string |
+| control/cases.rb:90:9:90:11 | "foo" | foo |
+| control/cases.rb:90:13:90:15 | "bar" | bar |
+| control/cases.rb:91:9:91:11 | :"foo" | foo |
+| control/cases.rb:91:13:91:15 | :"bar" | bar |
+| control/cases.rb:92:6:92:17 | /.*abc[0-9]/ | .*abc[0-9] |
+| control/cases.rb:93:6:93:6 | 5 | 5 |
+| control/cases.rb:93:11:93:12 | 10 | 10 |
+| control/cases.rb:94:9:94:10 | 10 | 10 |
+| control/cases.rb:95:6:95:6 | 5 | 5 |
| control/cases.rb:96:6:96:6 | 5 | 5 |
-| control/cases.rb:97:6:97:6 | 5 | 5 |
-| control/cases.rb:98:6:98:6 | 5 | 5 |
-| control/cases.rb:98:23:98:30 | "string" | string |
-| control/cases.rb:102:6:102:8 | nil | nil |
-| control/cases.rb:102:19:102:22 | true | true |
-| control/cases.rb:102:26:102:30 | false | false |
-| control/cases.rb:102:34:102:41 | __LINE__ | 102 |
-| control/cases.rb:102:45:102:52 | __FILE__ | control/cases.rb |
-| control/cases.rb:102:56:102:67 | __ENCODING__ | UTF-8 |
-| control/cases.rb:103:18:103:19 | 10 | 10 |
-| control/cases.rb:104:6:104:9 | :foo | foo |
-| control/cases.rb:105:6:105:15 | :"foo bar" | foo bar |
-| control/cases.rb:106:7:106:7 | 5 | 5 |
-| control/cases.rb:106:12:106:13 | 10 | 10 |
-| control/cases.rb:107:7:107:7 | 1 | 1 |
-| control/cases.rb:108:7:108:7 | 0 | 0 |
-| control/cases.rb:108:11:108:12 | "" | |
-| control/cases.rb:127:11:127:11 | 1 | 1 |
-| control/cases.rb:127:14:127:14 | 2 | 2 |
-| control/cases.rb:128:18:128:18 | 1 | 1 |
-| control/cases.rb:136:7:136:7 | :x | x |
-| control/cases.rb:137:16:137:16 | :x | x |
-| control/cases.rb:137:18:137:18 | 1 | 1 |
-| control/cases.rb:138:16:138:16 | :x | x |
-| control/cases.rb:138:18:138:18 | 1 | 1 |
-| control/cases.rb:138:21:138:21 | :a | a |
-| control/cases.rb:139:11:139:11 | :y | y |
-| control/cases.rb:141:11:141:11 | :a | a |
-| control/cases.rb:141:14:141:14 | 1 | 1 |
+| control/cases.rb:100:6:100:8 | nil | nil |
+| control/cases.rb:100:19:100:22 | true | true |
+| control/cases.rb:100:26:100:30 | false | false |
+| control/cases.rb:100:34:100:41 | __LINE__ | 100 |
+| control/cases.rb:100:45:100:52 | __FILE__ | control/cases.rb |
+| control/cases.rb:100:56:100:67 | __ENCODING__ | UTF-8 |
+| control/cases.rb:101:18:101:19 | 10 | 10 |
+| control/cases.rb:102:6:102:9 | :foo | foo |
+| control/cases.rb:103:6:103:15 | :"foo bar" | foo bar |
+| control/cases.rb:104:7:104:7 | 5 | 5 |
+| control/cases.rb:104:12:104:13 | 10 | 10 |
+| control/cases.rb:105:7:105:7 | 1 | 1 |
+| control/cases.rb:106:7:106:7 | 0 | 0 |
+| control/cases.rb:106:11:106:12 | "" | |
+| control/cases.rb:111:6:111:6 | 5 | 5 |
+| control/cases.rb:111:11:111:13 | foo | 42 |
+| control/cases.rb:111:17:111:24 | "string" | string |
+| control/cases.rb:130:11:130:11 | 1 | 1 |
+| control/cases.rb:130:14:130:14 | 2 | 2 |
+| control/cases.rb:131:18:131:18 | 1 | 1 |
+| control/cases.rb:139:7:139:7 | :x | x |
+| control/cases.rb:140:16:140:16 | :x | x |
+| control/cases.rb:140:18:140:18 | 1 | 1 |
+| control/cases.rb:141:16:141:16 | :x | x |
+| control/cases.rb:141:18:141:18 | 1 | 1 |
+| control/cases.rb:141:21:141:21 | :a | a |
+| control/cases.rb:142:11:142:11 | :y | y |
+| control/cases.rb:144:11:144:11 | :a | a |
+| control/cases.rb:144:14:144:14 | 1 | 1 |
| control/conditionals.rb:2:5:2:5 | 0 | 0 |
| control/conditionals.rb:3:5:3:5 | 0 | 0 |
| control/conditionals.rb:4:5:4:5 | 0 | 0 |
diff --git a/ruby/ql/test/library-tests/ast/control/CaseExpr.expected b/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
index bac914916a7..356b4ee3831 100644
--- a/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
+++ b/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
@@ -3,10 +3,11 @@ caseValues
| cases.rb:26:1:29:3 | case ... | cases.rb:26:6:26:9 | call to expr |
| cases.rb:31:1:37:3 | case ... | cases.rb:31:6:31:9 | call to expr |
| cases.rb:39:1:80:3 | case ... | cases.rb:39:6:39:9 | call to expr |
-| cases.rb:86:1:109:3 | case ... | cases.rb:86:6:86:9 | call to expr |
-| cases.rb:113:1:121:3 | case ... | cases.rb:113:6:113:9 | call to expr |
-| cases.rb:125:1:130:3 | case ... | cases.rb:125:6:125:9 | call to expr |
-| cases.rb:134:1:142:3 | case ... | cases.rb:134:6:134:9 | call to expr |
+| cases.rb:86:1:108:3 | case ... | cases.rb:86:6:86:9 | call to expr |
+| cases.rb:110:1:112:3 | case ... | cases.rb:110:6:110:9 | call to expr |
+| cases.rb:116:1:124:3 | case ... | cases.rb:116:6:116:9 | call to expr |
+| cases.rb:128:1:133:3 | case ... | cases.rb:128:6:128:9 | call to expr |
+| cases.rb:137:1:145:3 | case ... | cases.rb:137:6:137:9 | call to expr |
caseNoValues
| cases.rb:18:1:22:3 | case ... |
caseElseBranches
@@ -16,10 +17,11 @@ caseElseBranches
caseNoElseBranches
| cases.rb:18:1:22:3 | case ... |
| cases.rb:39:1:80:3 | case ... |
-| cases.rb:86:1:109:3 | case ... |
-| cases.rb:113:1:121:3 | case ... |
-| cases.rb:125:1:130:3 | case ... |
-| cases.rb:134:1:142:3 | case ... |
+| cases.rb:86:1:108:3 | case ... |
+| cases.rb:110:1:112:3 | case ... |
+| cases.rb:116:1:124:3 | case ... |
+| cases.rb:128:1:133:3 | case ... |
+| cases.rb:137:1:145:3 | case ... |
caseWhenBranches
| cases.rb:8:1:15:3 | case ... | cases.rb:9:1:10:7 | when ... | 0 | cases.rb:9:6:9:6 | b | cases.rb:9:7:10:7 | then ... |
| cases.rb:8:1:15:3 | case ... | cases.rb:11:1:12:7 | when ... | 0 | cases.rb:11:6:11:6 | c | cases.rb:11:10:12:7 | then ... |
@@ -79,43 +81,43 @@ caseAllBranches
| cases.rb:39:1:80:3 | case ... | 37 | cases.rb:77:3:77:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 38 | cases.rb:78:3:78:8 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 39 | cases.rb:79:3:79:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 0 | cases.rb:87:3:87:6 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 1 | cases.rb:88:3:88:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 2 | cases.rb:89:3:89:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 3 | cases.rb:90:3:90:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 4 | cases.rb:91:3:91:16 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 5 | cases.rb:92:3:92:16 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 6 | cases.rb:93:3:93:17 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 7 | cases.rb:94:3:94:12 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 8 | cases.rb:95:3:95:10 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 9 | cases.rb:96:3:96:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 10 | cases.rb:97:3:97:11 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 11 | cases.rb:98:3:98:30 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 12 | cases.rb:99:3:99:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 13 | cases.rb:100:3:100:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 14 | cases.rb:101:3:101:15 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 15 | cases.rb:102:3:102:67 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 16 | cases.rb:103:3:103:21 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 17 | cases.rb:104:3:104:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 18 | cases.rb:105:3:105:15 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 19 | cases.rb:106:3:106:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 20 | cases.rb:107:3:107:11 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 21 | cases.rb:108:3:108:23 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 0 | cases.rb:114:3:114:8 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 1 | cases.rb:115:3:115:9 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 2 | cases.rb:116:3:116:11 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 3 | cases.rb:117:3:117:16 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 4 | cases.rb:118:3:118:11 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 5 | cases.rb:119:3:119:12 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 6 | cases.rb:120:3:120:25 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 0 | cases.rb:126:3:126:15 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 1 | cases.rb:127:3:127:20 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 2 | cases.rb:128:3:128:23 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 3 | cases.rb:129:3:129:20 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 0 | cases.rb:135:3:135:8 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 1 | cases.rb:136:3:136:10 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 2 | cases.rb:137:3:137:21 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 3 | cases.rb:138:3:138:33 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 4 | cases.rb:139:3:139:14 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 5 | cases.rb:140:3:140:15 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 6 | cases.rb:141:3:141:23 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 0 | cases.rb:87:3:87:6 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 1 | cases.rb:88:3:88:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 2 | cases.rb:89:3:89:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 3 | cases.rb:90:3:90:16 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 4 | cases.rb:91:3:91:16 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 5 | cases.rb:92:3:92:17 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 6 | cases.rb:93:3:93:12 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 7 | cases.rb:94:3:94:10 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 8 | cases.rb:95:3:95:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 9 | cases.rb:96:3:96:11 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 10 | cases.rb:97:3:97:8 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 11 | cases.rb:98:3:98:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 12 | cases.rb:99:3:99:15 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 13 | cases.rb:100:3:100:67 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 14 | cases.rb:101:3:101:21 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 15 | cases.rb:102:3:102:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 16 | cases.rb:103:3:103:15 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 17 | cases.rb:104:3:104:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 18 | cases.rb:105:3:105:11 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 19 | cases.rb:106:3:106:23 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 20 | cases.rb:107:3:107:8 | in ... then ... |
+| cases.rb:110:1:112:3 | case ... | 0 | cases.rb:111:3:111:30 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 0 | cases.rb:117:3:117:8 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 1 | cases.rb:118:3:118:9 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 2 | cases.rb:119:3:119:11 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 3 | cases.rb:120:3:120:16 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 4 | cases.rb:121:3:121:11 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 5 | cases.rb:122:3:122:12 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 6 | cases.rb:123:3:123:25 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 0 | cases.rb:129:3:129:15 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 1 | cases.rb:130:3:130:20 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 2 | cases.rb:131:3:131:23 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 3 | cases.rb:132:3:132:20 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 0 | cases.rb:138:3:138:8 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 1 | cases.rb:139:3:139:10 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 2 | cases.rb:140:3:140:21 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 3 | cases.rb:141:3:141:33 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 4 | cases.rb:142:3:142:14 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 5 | cases.rb:143:3:143:15 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 6 | cases.rb:144:3:144:23 | in ... then ... |
diff --git a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
index 9226236873a..953bc10600d 100644
--- a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
+++ b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
@@ -3,10 +3,11 @@
| cases.rb:26:1:29:3 | case ... | CaseExpr |
| cases.rb:31:1:37:3 | case ... | CaseExpr |
| cases.rb:39:1:80:3 | case ... | CaseExpr |
-| cases.rb:86:1:109:3 | case ... | CaseExpr |
-| cases.rb:113:1:121:3 | case ... | CaseExpr |
-| cases.rb:125:1:130:3 | case ... | CaseExpr |
-| cases.rb:134:1:142:3 | case ... | CaseExpr |
+| cases.rb:86:1:108:3 | case ... | CaseExpr |
+| cases.rb:110:1:112:3 | case ... | CaseExpr |
+| cases.rb:116:1:124:3 | case ... | CaseExpr |
+| cases.rb:128:1:133:3 | case ... | CaseExpr |
+| cases.rb:137:1:145:3 | case ... | CaseExpr |
| conditionals.rb:10:1:12:3 | if ... | IfExpr |
| conditionals.rb:15:1:19:3 | if ... | IfExpr |
| conditionals.rb:22:1:30:3 | if ... | IfExpr |
diff --git a/ruby/ql/test/library-tests/ast/control/cases.rb b/ruby/ql/test/library-tests/ast/control/cases.rb
index 07bc117b7cb..2c92839d736 100644
--- a/ruby/ql/test/library-tests/ast/control/cases.rb
+++ b/ruby/ql/test/library-tests/ast/control/cases.rb
@@ -86,7 +86,6 @@ foo = 42
case expr
in 5
in ^foo
- in var
in "string"
in %w(foo bar)
in %i(foo bar)
@@ -95,7 +94,6 @@ case expr
in .. 10
in 5 ..
in 5 => x
- in 5 | ^foo | var | "string"
in Foo
in Foo::Bar
in ::Foo::Bar
@@ -106,6 +104,11 @@ case expr
in -5 | +10
in (1 ..)
in (0 | "" | [] | {})
+ in var
+end
+
+case expr
+ in 5 | ^foo | "string" | var
end
# array patterns
From 322f8356dd2f960ca46de880b351e8f143de9bfc Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 10:59:53 +0100
Subject: [PATCH 015/296] Ruby: Include `StringComponent`s in the CFG
---
.../internal/ControlFlowGraphImpl.qll | 4 +
.../controlflow/graph/Cfg.expected | 747 ++++++++++++++----
2 files changed, 608 insertions(+), 143 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index 1576ff51938..22615dc2575 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1350,6 +1350,10 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getComponent(i) }
}
+ private class StringComponentComponentTree extends LeafTree, StringComponent {
+ StringComponentComponentTree() { not this instanceof StringInterpolationComponent }
+ }
+
private class ToplevelTree extends BodyStmtTree, Toplevel {
final override AstNode getBodyChild(int i, boolean rescuable) {
result = this.getBeginBlock(i) and rescuable = true
diff --git a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
index a6f06fc0f71..c4e4780e1ca 100644
--- a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
+++ b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
@@ -103,10 +103,10 @@ break_ensure.rb:
#-----| -> [ensure: raise] then ...
# 9| self
-#-----| -> "elements nil"
+#-----| -> elements nil
# 9| [ensure: raise] self
-#-----| -> [ensure: raise] "elements nil"
+#-----| -> [ensure: raise] elements nil
# 9| "elements nil"
#-----| -> call to puts
@@ -114,6 +114,12 @@ break_ensure.rb:
# 9| [ensure: raise] "elements nil"
#-----| -> [ensure: raise] call to puts
+# 9| elements nil
+#-----| -> "elements nil"
+
+# 9| [ensure: raise] elements nil
+#-----| -> [ensure: raise] "elements nil"
+
# 13| enter m2
#-----| -> x
@@ -222,13 +228,13 @@ break_ensure.rb:
#-----| -> [ensure: raise] then ...
# 21| self
-#-----| -> "y nil"
+#-----| -> y nil
# 21| [ensure: break] self
-#-----| -> [ensure: break] "y nil"
+#-----| -> [ensure: break] y nil
# 21| [ensure: raise] self
-#-----| -> [ensure: raise] "y nil"
+#-----| -> [ensure: raise] y nil
# 21| "y nil"
#-----| -> call to puts
@@ -239,6 +245,15 @@ break_ensure.rb:
# 21| [ensure: raise] "y nil"
#-----| -> [ensure: raise] call to puts
+# 21| y nil
+#-----| -> "y nil"
+
+# 21| [ensure: break] y nil
+#-----| -> [ensure: break] "y nil"
+
+# 21| [ensure: raise] y nil
+#-----| -> [ensure: raise] "y nil"
+
# 27| enter m3
#-----| -> x
@@ -382,11 +397,14 @@ break_ensure.rb:
#-----| -> exit m3 (normal)
# 41| self
-#-----| -> "Done"
+#-----| -> Done
# 41| "Done"
#-----| -> call to puts
+# 41| Done
+#-----| -> "Done"
+
# 44| enter m4
#-----| -> x
@@ -543,11 +561,14 @@ case.rb:
#-----| -> then ...
# 3| self
-#-----| -> "x2"
+#-----| -> x2
# 3| "x2"
#-----| -> call to puts
+# 3| x2
+#-----| -> "x2"
+
# 4| when ...
#-----| -> 2
@@ -562,11 +583,14 @@ case.rb:
#-----| -> then ...
# 4| self
-#-----| -> "2"
+#-----| -> 2
# 4| "2"
#-----| -> call to puts
+# 4| 2
+#-----| -> "2"
+
# 8| enter case_match
#-----| -> value
@@ -745,11 +769,14 @@ case.rb:
#-----| raise -> exit -> { ... } (abnormal)
# 28| self
-#-----| -> "oops"
+#-----| -> oops
# 28| "oops"
#-----| -> call to raise
+# 28| oops
+#-----| -> "oops"
+
# 32| enter case_match_array
#-----| -> value
@@ -1056,12 +1083,15 @@ case.rb:
#-----| no-match -> in ... then ...
# 75| in ... then ...
-#-----| -> "string"
+#-----| -> string
# 75| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 75| string
+#-----| -> "string"
+
# 76| in ... then ...
#-----| -> Array
@@ -1070,14 +1100,20 @@ case.rb:
#-----| no-match -> in ... then ...
# 76| Array
-#-----| -> "foo"
+#-----| -> foo
# 76| "foo"
-#-----| -> "bar"
+#-----| -> bar
+
+# 76| foo
+#-----| -> "foo"
# 76| "bar"
#-----| -> call to []
+# 76| bar
+#-----| -> "bar"
+
# 77| in ... then ...
#-----| -> Array
@@ -1086,21 +1122,30 @@ case.rb:
#-----| no-match -> in ... then ...
# 77| Array
-#-----| -> :"foo"
+#-----| -> foo
# 77| :"foo"
-#-----| -> :"bar"
+#-----| -> bar
+
+# 77| foo
+#-----| -> :"foo"
# 77| :"bar"
#-----| -> call to []
+# 77| bar
+#-----| -> :"bar"
+
# 78| in ... then ...
-#-----| -> /.*abc[0-9]/
+#-----| -> .*abc[0-9]
# 78| /.*abc[0-9]/
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 78| .*abc[0-9]
+#-----| -> /.*abc[0-9]/
+
# 79| in ... then ...
#-----| -> 5
@@ -1162,12 +1207,15 @@ case.rb:
# 83| foo
#-----| match -> case ...
-#-----| no-match -> "string"
+#-----| no-match -> string
# 83| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 83| string
+#-----| -> "string"
+
# 84| in ... then ...
#-----| -> Foo
@@ -1213,12 +1261,15 @@ case.rb:
#-----| no-match -> in ... then ...
# 87| in ... then ...
-#-----| -> :"foo bar"
+#-----| -> foo bar
# 87| :"foo bar"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 87| foo bar
+#-----| -> :"foo bar"
+
# 88| in ... then ...
#-----| -> ... | ...
@@ -1372,29 +1423,38 @@ cfg.html.erb:
#-----| -> self
# 6| self
-#-----| -> "application"
+#-----| -> application
# 6| "application"
#-----| -> :media
+# 6| application
+#-----| -> "application"
+
# 6| Pair
#-----| -> call to stylesheet_link_tag
# 6| :media
-#-----| -> "all"
+#-----| -> all
# 6| "all"
#-----| -> Pair
+# 6| all
+#-----| -> "all"
+
# 12| call to link_to
#-----| -> self
# 12| self
-#-----| -> "A"
+#-----| -> A
# 12| "A"
#-----| -> self
+# 12| A
+#-----| -> "A"
+
# 12| call to a
#-----| -> :id
@@ -1402,7 +1462,7 @@ cfg.html.erb:
#-----| -> call to a
# 12| :id
-#-----| -> "a"
+#-----| -> a
# 12| Pair
#-----| -> call to link_to
@@ -1410,15 +1470,21 @@ cfg.html.erb:
# 12| "a"
#-----| -> Pair
+# 12| a
+#-----| -> "a"
+
# 15| call to link_to
#-----| -> self
# 15| self
-#-----| -> "B"
+#-----| -> B
# 15| "B"
#-----| -> self
+# 15| B
+#-----| -> "B"
+
# 15| call to a
#-----| -> call to link_to
@@ -1429,11 +1495,14 @@ cfg.html.erb:
#-----| -> self
# 16| self
-#-----| -> "C"
+#-----| -> C
# 16| "C"
#-----| -> self
+# 16| C
+#-----| -> "C"
+
# 16| call to b
#-----| -> call to link_to
@@ -1457,11 +1526,14 @@ cfg.html.erb:
#-----| -> then ...
# 19| self
-#-----| -> "D"
+#-----| -> D
# 19| "D"
#-----| -> self
+# 19| D
+#-----| -> "D"
+
# 19| call to d
#-----| -> call to link_to
@@ -1475,11 +1547,14 @@ cfg.html.erb:
#-----| -> else ...
# 21| self
-#-----| -> "E"
+#-----| -> E
# 21| "E"
#-----| -> self
+# 21| E
+#-----| -> "E"
+
# 21| call to e
#-----| -> call to link_to
@@ -1552,10 +1627,13 @@ cfg.rb:
#-----| -> Array
# 7| Array
-#-----| -> b
+#-----| -> one
# 7| :"one#{...}"
-#-----| -> :"another"
+#-----| -> another
+
+# 7| one
+#-----| -> b
# 7| #{...}
#-----| -> :"one#{...}"
@@ -1566,14 +1644,20 @@ cfg.rb:
# 7| :"another"
#-----| -> call to []
+# 7| another
+#-----| -> :"another"
+
# 9| call to []
#-----| -> self
# 9| Array
-#-----| -> b
+#-----| -> one
# 9| "one#{...}"
-#-----| -> "another"
+#-----| -> another
+
+# 9| one
+#-----| -> b
# 9| #{...}
#-----| -> "one#{...}"
@@ -1584,6 +1668,9 @@ cfg.rb:
# 9| "another"
#-----| -> call to []
+# 9| another
+#-----| -> "another"
+
# 12| call to puts
#-----| -> END { ... }
@@ -1600,11 +1687,14 @@ cfg.rb:
#-----| -> BEGIN { ... }
# 16| self
-#-----| -> "hello"
+#-----| -> hello
# 16| "hello"
#-----| -> call to puts
+# 16| hello
+#-----| -> "hello"
+
# 19| END { ... }
#-----| -> 41
@@ -1731,11 +1821,14 @@ cfg.rb:
#-----| -> then ...
# 42| self
-#-----| -> "one"
+#-----| -> one
# 42| "one"
#-----| -> call to puts
+# 42| one
+#-----| -> "one"
+
# 43| when ...
#-----| -> 2
@@ -1758,11 +1851,14 @@ cfg.rb:
#-----| -> then ...
# 43| self
-#-----| -> "some"
+#-----| -> some
# 43| "some"
#-----| -> call to puts
+# 43| some
+#-----| -> "some"
+
# 44| else ...
#-----| -> case ...
@@ -1770,11 +1866,14 @@ cfg.rb:
#-----| -> else ...
# 44| self
-#-----| -> "many"
+#-----| -> many
# 44| "many"
#-----| -> call to puts
+# 44| many
+#-----| -> "many"
+
# 47| case ...
#-----| -> chained
@@ -1798,11 +1897,14 @@ cfg.rb:
#-----| -> then ...
# 48| self
-#-----| -> "one"
+#-----| -> one
# 48| "one"
#-----| -> call to puts
+# 48| one
+#-----| -> "one"
+
# 49| when ...
#-----| -> b
@@ -1833,16 +1935,19 @@ cfg.rb:
#-----| -> then ...
# 49| self
-#-----| -> "some"
+#-----| -> some
# 49| "some"
#-----| -> call to puts
+# 49| some
+#-----| -> "some"
+
# 52| ... = ...
#-----| -> character
# 52| chained
-#-----| -> "a"
+#-----| -> a
# 52| "a"
#-----| -> chained
@@ -1850,8 +1955,11 @@ cfg.rb:
# 52| "..." "..."
#-----| -> ... = ...
+# 52| a
+#-----| -> "a"
+
# 52| "#{...}"
-#-----| -> "string"
+#-----| -> string
# 52| #{...}
#-----| -> "#{...}"
@@ -1862,6 +1970,9 @@ cfg.rb:
# 52| "string"
#-----| -> "..." "..."
+# 52| string
+#-----| -> "string"
+
# 54| ... = ...
#-----| -> Silly
@@ -1893,8 +2004,8 @@ cfg.rb:
#-----| -> self
# 60| ... < ...
-#-----| true -> "hello"
-#-----| false -> "bye"
+#-----| true -> hello
+#-----| false -> bye
# 60| ... ? ... : ...
#-----| -> ... = ...
@@ -1911,18 +2022,27 @@ cfg.rb:
# 60| "hello"
#-----| -> ... ? ... : ...
+# 60| hello
+#-----| -> "hello"
+
# 60| "bye"
#-----| -> ... ? ... : ...
+# 60| bye
+#-----| -> "bye"
+
# 61| ... = ...
#-----| -> __synth__0
# 61| C
-#-----| -> "constant"
+#-----| -> constant
# 61| "constant"
#-----| -> ... = ...
+# 61| constant
+#-----| -> "constant"
+
# 62| ...
#-----| -> pattern
@@ -2111,11 +2231,14 @@ cfg.rb:
#-----| -> exit print (normal)
# 70| self
-#-----| -> "silly"
+#-----| -> silly
# 70| "silly"
#-----| -> call to puts
+# 70| silly
+#-----| -> "silly"
+
# 74| ... = ...
#-----| -> x
@@ -2179,11 +2302,14 @@ cfg.rb:
#-----| -> else ...
# 83| self
-#-----| -> "ok"
+#-----| -> ok
# 83| "ok"
#-----| -> call to puts
+# 83| ok
+#-----| -> "ok"
+
# 84| ensure ...
#-----| -> escape
@@ -2191,26 +2317,35 @@ cfg.rb:
#-----| -> ensure ...
# 85| self
-#-----| -> "end"
+#-----| -> end
# 85| "end"
#-----| -> call to puts
+# 85| end
+#-----| -> "end"
+
# 88| ... = ...
#-----| -> Array
# 88| escape
-#-----| -> x
+#-----| -> \u1234
# 88| "\u1234#{...}\n"
#-----| -> ... = ...
+# 88| \u1234
+#-----| -> x
+
# 88| #{...}
-#-----| -> "\u1234#{...}\n"
+#-----| -> \n
# 88| x
#-----| -> #{...}
+# 88| \n
+#-----| -> "\u1234#{...}\n"
+
# 90| enter { ... }
#-----| -> __synth__0__1
@@ -2290,31 +2425,43 @@ cfg.rb:
#-----| -> map2
# 97| map1
-#-----| -> "a"
+#-----| -> a
# 97| {...}
#-----| -> ... = ...
# 97| Pair
-#-----| -> "c"
+#-----| -> c
# 97| "a"
-#-----| -> "b"
+#-----| -> b
+
+# 97| a
+#-----| -> "a"
# 97| "b"
#-----| -> Pair
+# 97| b
+#-----| -> "b"
+
# 97| Pair
#-----| -> :e
# 97| "c"
-#-----| -> "d"
+#-----| -> d
+
+# 97| c
+#-----| -> "c"
# 97| "d"
#-----| -> Pair
+# 97| d
+#-----| -> "d"
+
# 97| :e
-#-----| -> "f"
+#-----| -> f
# 97| Pair
#-----| -> {...}
@@ -2322,6 +2469,9 @@ cfg.rb:
# 97| "f"
#-----| -> Pair
+# 97| f
+#-----| -> "f"
+
# 98| ... = ...
#-----| -> parameters
@@ -2332,7 +2482,7 @@ cfg.rb:
#-----| -> ... = ...
# 98| ** ...
-#-----| -> "x"
+#-----| -> x
# 98| map1
#-----| -> ** ...
@@ -2341,11 +2491,17 @@ cfg.rb:
#-----| -> map1
# 98| "x"
-#-----| -> "y"
+#-----| -> y
+
+# 98| x
+#-----| -> "x"
# 98| "y"
#-----| -> Pair
+# 98| y
+#-----| -> "y"
+
# 98| ** ...
#-----| -> {...}
@@ -2401,25 +2557,32 @@ cfg.rb:
#-----| -> table
# 106| type
-#-----| -> "healthy"
+#-----| -> healthy
# 106| "healthy"
#-----| -> ... = ...
+# 106| healthy
+#-----| -> "healthy"
+
# 107| ... = ...
#-----| -> self
# 107| table
-#-----| -> "food"
+#-----| -> food
# 107| "food"
#-----| -> ... = ...
+# 107| food
+#-----| -> "food"
+
# 108| call to puts
#-----| -> b
# 108| self
-#-----| -> table
+#-----| ->
+#-----| SELECT * FROM
# 108| ( ... )
#-----| -> call to puts
@@ -2427,18 +2590,44 @@ cfg.rb:
# 108| < ( ... )
+# 108|
+# 108| SELECT * FROM
+#-----| -> table
+
# 109| #{...}
-#-----| -> type
+#-----| ->
# 109| table
#-----| -> #{...}
+# 109|
+#-----| -> \n
+
+# 109| \n
+#-----| ->
+#-----| WHERE
+
+# 109|
+# 109| WHERE
+#-----| -> type
+
# 110| #{...}
-#-----| -> < = true
# 110| type
#-----| -> #{...}
+# 110| = true
+#-----| -> \n
+
+# 110| \n
+#-----| ->
+#-----|
+
+# 110|
+# 110|
+#-----| -> < ... if ...
@@ -2446,11 +2635,14 @@ cfg.rb:
#-----| -> C
# 113| self
-#-----| -> "hi"
+#-----| -> hi
# 113| "hi"
#-----| -> call to puts
+# 113| hi
+#-----| -> "hi"
+
# 113| ... > ...
#-----| false -> ... if ...
#-----| true -> self
@@ -2620,17 +2812,29 @@ cfg.rb:
#-----| -> Constant
# 129| regex
-#-----| -> range
+#-----| -> hello
# 129| /hello\s+[#{...}]/
#-----| -> ... = ...
+# 129| hello
+#-----| -> \s
+
+# 129| \s
+#-----| -> +[
+
+# 129| +[
+#-----| -> range
+
# 129| #{...}
-#-----| -> /hello\s+[#{...}]/
+#-----| -> ]
# 129| range
#-----| -> #{...}
+# 129| ]
+#-----| -> /hello\s+[#{...}]/
+
# 130| ... = ...
#-----| -> EmptyClass
@@ -2663,11 +2867,14 @@ cfg.rb:
#-----| -> ... rescue ...
# 136| self
-#-----| -> "div by zero"
+#-----| -> div by zero
# 136| "div by zero"
#-----| -> call to puts
+# 136| div by zero
+#-----| -> "div by zero"
+
# 138| ...
#-----| -> M
@@ -2770,11 +2977,14 @@ cfg.rb:
#-----| -> self
# 146| self
-#-----| -> "singleton"
+#-----| -> singleton
# 146| "singleton"
#-----| -> call to puts
+# 146| singleton
+#-----| -> "singleton"
+
# 147| call to puts
#-----| -> exit print (normal)
@@ -2867,13 +3077,16 @@ cfg.rb:
#-----| -> symbol
# 160| scriptfile
-#-----| -> self
+#-----| -> cat "
# 160| `cat "#{...}"`
#-----| -> ... = ...
+# 160| cat "
+#-----| -> self
+
# 160| #{...}
-#-----| -> `cat "#{...}"`
+#-----| -> "
# 160| call to __FILE__
#-----| -> #{...}
@@ -2881,6 +3094,9 @@ cfg.rb:
# 160| self
#-----| -> call to __FILE__
+# 160| "
+#-----| -> `cat "#{...}"`
+
# 162| ... = ...
#-----| -> delimited_symbol
@@ -2894,11 +3110,14 @@ cfg.rb:
#-----| -> x
# 164| delimited_symbol
-#-----| -> 12
+#-----| -> goodbye-
# 164| :"goodbye-#{...}"
#-----| -> ... = ...
+# 164| goodbye-
+#-----| -> 12
+
# 164| #{...}
#-----| -> :"goodbye-#{...}"
@@ -2970,11 +3189,14 @@ cfg.rb:
#-----| -> then ...
# 172| self
-#-----| -> "hi"
+#-----| -> hi
# 172| "hi"
#-----| -> call to puts
+# 172| hi
+#-----| -> "hi"
+
# 172| else ...
#-----| -> unless ...
@@ -2982,11 +3204,14 @@ cfg.rb:
#-----| -> else ...
# 172| self
-#-----| -> "bye"
+#-----| -> bye
# 172| "bye"
#-----| -> call to puts
+# 172| bye
+#-----| -> "bye"
+
# 174| call to puts
#-----| -> ... unless ...
@@ -2994,11 +3219,14 @@ cfg.rb:
#-----| -> x
# 174| self
-#-----| -> "hi"
+#-----| -> hi
# 174| "hi"
#-----| -> call to puts
+# 174| hi
+#-----| -> "hi"
+
# 174| ... == ...
#-----| true -> ... unless ...
#-----| false -> self
@@ -3044,11 +3272,14 @@ cfg.rb:
#-----| -> do ...
# 176| self
-#-----| -> "hello"
+#-----| -> hello
# 176| "hello"
#-----| -> call to puts
+# 176| hello
+#-----| -> "hello"
+
# 178| ... = ...
#-----| -> i
@@ -3068,11 +3299,14 @@ cfg.rb:
#-----| -> i
# 179| self
-#-----| -> "hello"
+#-----| -> hello
# 179| "hello"
#-----| -> call to puts
+# 179| hello
+#-----| -> "hello"
+
# 179| i
#-----| -> i
@@ -3173,11 +3407,14 @@ cfg.rb:
#-----| -> i
# 188| self
-#-----| -> "hello"
+#-----| -> hello
# 188| "hello"
#-----| -> call to puts
+# 188| hello
+#-----| -> "hello"
+
# 188| i
#-----| -> i
@@ -3920,11 +4157,14 @@ exit.rb:
#-----| -> exit m1 (normal)
# 5| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 5| "x <= 2"
#-----| -> call to puts
+# 5| x <= 2
+#-----| -> "x <= 2"
+
# 8| enter m2
#-----| -> x
@@ -3959,20 +4199,26 @@ exit.rb:
#-----| exit -> exit m2 (abnormal)
# 10| self
-#-----| -> "abort!"
+#-----| -> abort!
# 10| "abort!"
#-----| -> call to abort
+# 10| abort!
+#-----| -> "abort!"
+
# 12| call to puts
#-----| -> exit m2 (normal)
# 12| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 12| "x <= 2"
#-----| -> call to puts
+# 12| x <= 2
+#-----| -> "x <= 2"
+
heredoc.rb:
# 1| enter double_heredoc
#-----| -> self
@@ -3997,14 +4243,28 @@ heredoc.rb:
#-----| -> exit double_heredoc (normal)
# 2| self
-#-----| -> <
+#-----| hello
+#-----|
# 2| < <
+#-----| world
+#-----|
# 2| < call to puts
+# 2|
+# 2| hello
+# 2|
+#-----| -> < < x
@@ -4048,11 +4308,14 @@ ifs.rb:
#-----| -> then ...
# 3| self
-#-----| -> "x is greater than 2"
+#-----| -> x is greater than 2
# 3| "x is greater than 2"
#-----| -> call to puts
+# 3| x is greater than 2
+#-----| -> "x is greater than 2"
+
# 4| elsif ...
#-----| -> if ...
@@ -4117,11 +4380,14 @@ ifs.rb:
#-----| -> then ...
# 5| self
-#-----| -> "x is 1"
+#-----| -> x is 1
# 5| "x is 1"
#-----| -> call to puts
+# 5| x is 1
+#-----| -> "x is 1"
+
# 6| else ...
#-----| -> elsif ...
@@ -4129,11 +4395,14 @@ ifs.rb:
#-----| -> else ...
# 7| self
-#-----| -> "I can't guess the number"
+#-----| -> I can't guess the number
# 7| "I can't guess the number"
#-----| -> call to puts
+# 7| I can't guess the number
+#-----| -> "I can't guess the number"
+
# 11| enter m2
#-----| -> b
@@ -4273,10 +4542,10 @@ ifs.rb:
#-----| return -> exit m4 (normal)
# 29| [false] ( ... )
-#-----| false -> "!b2 || !b3"
+#-----| false -> !b2 || !b3
# 29| [true] ( ... )
-#-----| true -> "b2 || b3"
+#-----| true -> b2 || b3
# 29| ... ? ... : ...
#-----| -> return
@@ -4302,9 +4571,15 @@ ifs.rb:
# 29| "b2 || b3"
#-----| -> ... ? ... : ...
+# 29| b2 || b3
+#-----| -> "b2 || b3"
+
# 29| "!b2 || !b3"
#-----| -> ... ? ... : ...
+# 29| !b2 || !b3
+#-----| -> "!b2 || !b3"
+
# 32| enter m5
#-----| -> b1
@@ -4335,10 +4610,10 @@ ifs.rb:
#-----| -> exit m5 (normal)
# 33| [false] ( ... )
-#-----| false -> "!b2 || !b4 || !b5"
+#-----| false -> !b2 || !b4 || !b5
# 33| [true] ( ... )
-#-----| true -> "b2 || b4 || b5"
+#-----| true -> b2 || b4 || b5
# 33| [false] if ...
#-----| false -> [false] ( ... )
@@ -4396,12 +4671,18 @@ ifs.rb:
# 33| "b2 || b4 || b5"
#-----| -> then ...
+# 33| b2 || b4 || b5
+#-----| -> "b2 || b4 || b5"
+
# 33| else ...
#-----| -> if ...
# 33| "!b2 || !b4 || !b5"
#-----| -> else ...
+# 33| !b2 || !b4 || !b5
+#-----| -> "!b2 || !b4 || !b5"
+
# 36| enter conditional_method_def
#-----| -> self
@@ -4420,11 +4701,14 @@ ifs.rb:
#-----| -> exit conditional_method_def (normal)
# 37| self
-#-----| -> "bla"
+#-----| -> bla
# 37| "bla"
#-----| -> call to puts
+# 37| bla
+#-----| -> "bla"
+
# 38| ... == ...
#-----| false -> conditional_method_def
#-----| true -> ... unless ...
@@ -4483,11 +4767,14 @@ ifs.rb:
#-----| -> then ...
# 48| self
-#-----| -> "true"
+#-----| -> true
# 48| "true"
#-----| -> call to puts
+# 48| true
+#-----| -> "true"
+
# 49| else ...
#-----| -> if ...
@@ -4495,11 +4782,14 @@ ifs.rb:
#-----| -> exit empty_else (normal)
# 51| self
-#-----| -> "done"
+#-----| -> done
# 51| "done"
#-----| -> call to puts
+# 51| done
+#-----| -> "done"
+
# 54| enter disjunct
#-----| -> b1
@@ -4547,11 +4837,14 @@ ifs.rb:
#-----| -> then ...
# 56| self
-#-----| -> "b1 or b2"
+#-----| -> b1 or b2
# 56| "b1 or b2"
#-----| -> call to puts
+# 56| b1 or b2
+#-----| -> "b1 or b2"
+
loops.rb:
# 1| enter m1
#-----| -> x
@@ -4721,20 +5014,26 @@ loops.rb:
#-----| -> do ...
# 19| self
-#-----| -> "Iter"
+#-----| -> Iter
# 19| "Iter"
#-----| -> call to puts
+# 19| Iter
+#-----| -> "Iter"
+
# 21| call to puts
#-----| -> exit m2 (normal)
# 21| self
-#-----| -> "Done"
+#-----| -> Done
# 21| "Done"
#-----| -> call to puts
+# 21| Done
+#-----| -> "Done"
+
# 24| enter m3
#-----| -> Array
@@ -4875,20 +5174,26 @@ raise.rb:
#-----| raise -> exit m1 (abnormal)
# 9| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 9| "x > 2"
#-----| -> call to raise
+# 9| x > 2
+#-----| -> "x > 2"
+
# 11| call to puts
#-----| -> exit m1 (normal)
# 11| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 11| "x <= 2"
#-----| -> call to puts
+# 11| x <= 2
+#-----| -> "x <= 2"
+
# 14| enter m2
#-----| -> b
@@ -4936,20 +5241,26 @@ raise.rb:
#-----| -> then ...
# 20| self
-#-----| -> "Rescued"
+#-----| -> Rescued
# 20| "Rescued"
#-----| -> call to puts
+# 20| Rescued
+#-----| -> "Rescued"
+
# 22| call to puts
#-----| -> exit m2 (normal)
# 22| self
-#-----| -> "End m2"
+#-----| -> End m2
# 22| "End m2"
#-----| -> call to puts
+# 22| End m2
+#-----| -> "End m2"
+
# 25| enter m3
#-----| -> b
@@ -4990,20 +5301,26 @@ raise.rb:
#-----| -> then ...
# 31| self
-#-----| -> "Rescued"
+#-----| -> Rescued
# 31| "Rescued"
#-----| -> call to puts
+# 31| Rescued
+#-----| -> "Rescued"
+
# 33| call to puts
#-----| -> exit m3 (normal)
# 33| self
-#-----| -> "End m3"
+#-----| -> End m3
# 33| "End m3"
#-----| -> call to puts
+# 33| End m3
+#-----| -> "End m3"
+
# 36| enter m4
#-----| -> b
@@ -5047,20 +5364,26 @@ raise.rb:
#-----| -> then ...
# 42| self
-#-----| -> "Rescued {e}"
+#-----| -> Rescued {e}
# 42| "Rescued {e}"
#-----| -> call to puts
+# 42| Rescued {e}
+#-----| -> "Rescued {e}"
+
# 44| call to puts
#-----| -> exit m4 (normal)
# 44| self
-#-----| -> "End m4"
+#-----| -> End m4
# 44| "End m4"
#-----| -> call to puts
+# 44| End m4
+#-----| -> "End m4"
+
# 47| enter m5
#-----| -> b
@@ -5101,11 +5424,14 @@ raise.rb:
#-----| -> exit m5 (normal)
# 54| self
-#-----| -> "End m5"
+#-----| -> End m5
# 54| "End m5"
#-----| -> call to puts
+# 54| End m5
+#-----| -> "End m5"
+
# 57| enter m6
#-----| -> b
@@ -5160,20 +5486,26 @@ raise.rb:
#-----| -> then ...
# 63| self
-#-----| -> "Rescued {e}"
+#-----| -> Rescued {e}
# 63| "Rescued {e}"
#-----| -> call to puts
+# 63| Rescued {e}
+#-----| -> "Rescued {e}"
+
# 65| call to puts
#-----| -> exit m6 (normal)
# 65| self
-#-----| -> "End m6"
+#-----| -> End m6
# 65| "End m6"
#-----| -> call to puts
+# 65| End m6
+#-----| -> "End m6"
+
# 68| enter m7
#-----| -> x
@@ -5209,17 +5541,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 70| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 70| "x > 2"
#-----| -> call to raise
+# 70| x > 2
+#-----| -> "x > 2"
+
# 71| elsif ...
#-----| -> if ...
# 71| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 71| x
@@ -5234,16 +5569,22 @@ raise.rb:
# 72| "x < 0"
#-----| -> return
+# 72| x < 0
+#-----| -> "x < 0"
+
# 74| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 74| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 74| "0 <= x <= 2"
#-----| -> call to puts
+# 74| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 75| ensure ...
#-----| -> exit m7 (normal)
@@ -5263,13 +5604,13 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 76| self
-#-----| -> "ensure"
+#-----| -> ensure
# 76| [ensure: return] self
-#-----| -> [ensure: return] "ensure"
+#-----| -> [ensure: return] ensure
# 76| [ensure: raise] self
-#-----| -> [ensure: raise] "ensure"
+#-----| -> [ensure: raise] ensure
# 76| "ensure"
#-----| -> call to puts
@@ -5280,6 +5621,15 @@ raise.rb:
# 76| [ensure: raise] "ensure"
#-----| -> [ensure: raise] call to puts
+# 76| ensure
+#-----| -> "ensure"
+
+# 76| [ensure: return] ensure
+#-----| -> [ensure: return] "ensure"
+
+# 76| [ensure: raise] ensure
+#-----| -> [ensure: raise] "ensure"
+
# 79| enter m8
#-----| -> x
@@ -5301,11 +5651,14 @@ raise.rb:
#-----| -> x
# 80| self
-#-----| -> "Begin m8"
+#-----| -> Begin m8
# 80| "Begin m8"
#-----| -> call to puts
+# 80| Begin m8
+#-----| -> "Begin m8"
+
# 82| if ...
#-----| -> self
@@ -5324,17 +5677,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 83| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 83| "x > 2"
#-----| -> call to raise
+# 83| x > 2
+#-----| -> "x > 2"
+
# 84| elsif ...
#-----| -> if ...
# 84| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 84| x
@@ -5349,16 +5705,22 @@ raise.rb:
# 85| "x < 0"
#-----| -> return
+# 85| x < 0
+#-----| -> "x < 0"
+
# 87| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 87| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 87| "0 <= x <= 2"
#-----| -> call to puts
+# 87| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 88| ensure ...
#-----| -> self
@@ -5378,13 +5740,13 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 89| self
-#-----| -> "ensure"
+#-----| -> ensure
# 89| [ensure: return] self
-#-----| -> [ensure: return] "ensure"
+#-----| -> [ensure: return] ensure
# 89| [ensure: raise] self
-#-----| -> [ensure: raise] "ensure"
+#-----| -> [ensure: raise] ensure
# 89| "ensure"
#-----| -> call to puts
@@ -5395,15 +5757,27 @@ raise.rb:
# 89| [ensure: raise] "ensure"
#-----| -> [ensure: raise] call to puts
+# 89| ensure
+#-----| -> "ensure"
+
+# 89| [ensure: return] ensure
+#-----| -> [ensure: return] "ensure"
+
+# 89| [ensure: raise] ensure
+#-----| -> [ensure: raise] "ensure"
+
# 91| call to puts
#-----| -> exit m8 (normal)
# 91| self
-#-----| -> "End m8"
+#-----| -> End m8
# 91| "End m8"
#-----| -> call to puts
+# 91| End m8
+#-----| -> "End m8"
+
# 94| enter m9
#-----| -> x
@@ -5432,11 +5806,14 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 95| self
-#-----| -> "Begin m9"
+#-----| -> Begin m9
# 95| "Begin m9"
#-----| -> call to puts
+# 95| Begin m9
+#-----| -> "Begin m9"
+
# 97| if ...
#-----| -> self
@@ -5455,17 +5832,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 98| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 98| "x > 2"
#-----| -> call to raise
+# 98| x > 2
+#-----| -> "x > 2"
+
# 99| elsif ...
#-----| -> if ...
# 99| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 99| x
@@ -5480,16 +5860,22 @@ raise.rb:
# 100| "x < 0"
#-----| -> return
+# 100| x < 0
+#-----| -> "x < 0"
+
# 102| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 102| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 102| "0 <= x <= 2"
#-----| -> call to puts
+# 102| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 103| ensure ...
#-----| -> self
@@ -5512,13 +5898,13 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 104| self
-#-----| -> "outer ensure"
+#-----| -> outer ensure
# 104| [ensure: return] self
-#-----| -> [ensure: return] "outer ensure"
+#-----| -> [ensure: return] outer ensure
# 104| [ensure: raise] self
-#-----| -> [ensure: raise] "outer ensure"
+#-----| -> [ensure: raise] outer ensure
# 104| "outer ensure"
#-----| -> call to puts
@@ -5529,6 +5915,15 @@ raise.rb:
# 104| [ensure: raise] "outer ensure"
#-----| -> [ensure: raise] call to puts
+# 104| outer ensure
+#-----| -> "outer ensure"
+
+# 104| [ensure: return] outer ensure
+#-----| -> [ensure: return] "outer ensure"
+
+# 104| [ensure: raise] outer ensure
+#-----| -> [ensure: raise] "outer ensure"
+
# 106| if ...
#-----| -> self
@@ -5560,13 +5955,13 @@ raise.rb:
#-----| raise -> [ensure: raise, ensure(1): raise] self
# 107| self
-#-----| -> "b1 is true"
+#-----| -> b1 is true
# 107| [ensure: return] self
-#-----| -> [ensure: return] "b1 is true"
+#-----| -> [ensure: return] b1 is true
# 107| [ensure: raise] self
-#-----| -> [ensure: raise] "b1 is true"
+#-----| -> [ensure: raise] b1 is true
# 107| "b1 is true"
#-----| -> call to raise
@@ -5577,6 +5972,15 @@ raise.rb:
# 107| [ensure: raise] "b1 is true"
#-----| -> [ensure: raise] call to raise
+# 107| b1 is true
+#-----| -> "b1 is true"
+
+# 107| [ensure: return] b1 is true
+#-----| -> [ensure: return] "b1 is true"
+
+# 107| [ensure: raise] b1 is true
+#-----| -> [ensure: raise] "b1 is true"
+
# 109| ensure ...
#-----| -> ensure ...
@@ -5620,22 +6024,22 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 110| self
-#-----| -> "inner ensure"
+#-----| -> inner ensure
# 110| [ensure(1): raise] self
-#-----| -> [ensure(1): raise] "inner ensure"
+#-----| -> [ensure(1): raise] inner ensure
# 110| [ensure: return] self
-#-----| -> [ensure: return] "inner ensure"
+#-----| -> [ensure: return] inner ensure
# 110| [ensure: return, ensure(1): raise] self
-#-----| -> [ensure: return, ensure(1): raise] "inner ensure"
+#-----| -> [ensure: return, ensure(1): raise] inner ensure
# 110| [ensure: raise] self
-#-----| -> [ensure: raise] "inner ensure"
+#-----| -> [ensure: raise] inner ensure
# 110| [ensure: raise, ensure(1): raise] self
-#-----| -> [ensure: raise, ensure(1): raise] "inner ensure"
+#-----| -> [ensure: raise, ensure(1): raise] inner ensure
# 110| "inner ensure"
#-----| -> call to puts
@@ -5655,16 +6059,37 @@ raise.rb:
# 110| [ensure: raise, ensure(1): raise] "inner ensure"
#-----| -> [ensure: raise, ensure(1): raise] call to puts
+# 110| inner ensure
+#-----| -> "inner ensure"
+
+# 110| [ensure(1): raise] inner ensure
+#-----| -> [ensure(1): raise] "inner ensure"
+
+# 110| [ensure: return] inner ensure
+#-----| -> [ensure: return] "inner ensure"
+
+# 110| [ensure: return, ensure(1): raise] inner ensure
+#-----| -> [ensure: return, ensure(1): raise] "inner ensure"
+
+# 110| [ensure: raise] inner ensure
+#-----| -> [ensure: raise] "inner ensure"
+
+# 110| [ensure: raise, ensure(1): raise] inner ensure
+#-----| -> [ensure: raise, ensure(1): raise] "inner ensure"
+
# 113| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 113| self
-#-----| -> "End m9"
+#-----| -> End m9
# 113| "End m9"
#-----| -> call to puts
+# 113| End m9
+#-----| -> "End m9"
+
# 114| ensure ...
#-----| -> exit m9 (normal)
@@ -5684,13 +6109,13 @@ raise.rb:
#-----| -> [ensure: raise] b2
# 115| self
-#-----| -> "method ensure"
+#-----| -> method ensure
# 115| [ensure: return] self
-#-----| -> [ensure: return] "method ensure"
+#-----| -> [ensure: return] method ensure
# 115| [ensure: raise] self
-#-----| -> [ensure: raise] "method ensure"
+#-----| -> [ensure: raise] method ensure
# 115| "method ensure"
#-----| -> call to puts
@@ -5701,6 +6126,15 @@ raise.rb:
# 115| [ensure: raise] "method ensure"
#-----| -> [ensure: raise] call to puts
+# 115| method ensure
+#-----| -> "method ensure"
+
+# 115| [ensure: return] method ensure
+#-----| -> [ensure: return] "method ensure"
+
+# 115| [ensure: raise] method ensure
+#-----| -> [ensure: raise] "method ensure"
+
# 116| if ...
#-----| -> ensure ...
@@ -5732,13 +6166,13 @@ raise.rb:
#-----| raise -> exit m9 (abnormal)
# 117| self
-#-----| -> "b2 is true"
+#-----| -> b2 is true
# 117| [ensure: return] self
-#-----| -> [ensure: return] "b2 is true"
+#-----| -> [ensure: return] b2 is true
# 117| [ensure: raise] self
-#-----| -> [ensure: raise] "b2 is true"
+#-----| -> [ensure: raise] b2 is true
# 117| "b2 is true"
#-----| -> call to raise
@@ -5749,6 +6183,15 @@ raise.rb:
# 117| [ensure: raise] "b2 is true"
#-----| -> [ensure: raise] call to raise
+# 117| b2 is true
+#-----| -> "b2 is true"
+
+# 117| [ensure: return] b2 is true
+#-----| -> [ensure: return] "b2 is true"
+
+# 117| [ensure: raise] b2 is true
+#-----| -> [ensure: raise] "b2 is true"
+
# 121| enter m10
#-----| -> p
@@ -5771,11 +6214,14 @@ raise.rb:
#-----| raise -> exit m10 (abnormal)
# 121| self
-#-----| -> "Exception"
+#-----| -> Exception
# 121| "Exception"
#-----| -> call to raise
+# 121| Exception
+#-----| -> "Exception"
+
# 124| ensure ...
#-----| -> exit m10 (normal)
@@ -5783,11 +6229,14 @@ raise.rb:
#-----| -> ensure ...
# 125| self
-#-----| -> "Will not get executed if p is..."
+#-----| -> Will not get executed if p is not supplied
# 125| "Will not get executed if p is..."
#-----| -> call to puts
+# 125| Will not get executed if p is not supplied
+#-----| -> "Will not get executed if p is..."
+
# 128| enter m11
#-----| -> b
@@ -5842,11 +6291,14 @@ raise.rb:
#-----| -> then ...
# 135| self
-#-----| -> "ExceptionB"
+#-----| -> ExceptionB
# 135| "ExceptionB"
#-----| -> call to puts
+# 135| ExceptionB
+#-----| -> "ExceptionB"
+
# 136| ensure ...
#-----| -> self
@@ -5860,10 +6312,10 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 137| self
-#-----| -> "Ensure"
+#-----| -> Ensure
# 137| [ensure: raise] self
-#-----| -> [ensure: raise] "Ensure"
+#-----| -> [ensure: raise] Ensure
# 137| "Ensure"
#-----| -> call to puts
@@ -5871,15 +6323,24 @@ raise.rb:
# 137| [ensure: raise] "Ensure"
#-----| -> [ensure: raise] call to puts
+# 137| Ensure
+#-----| -> "Ensure"
+
+# 137| [ensure: raise] Ensure
+#-----| -> [ensure: raise] "Ensure"
+
# 139| call to puts
#-----| -> exit m11 (normal)
# 139| self
-#-----| -> "End m11"
+#-----| -> End m11
# 139| "End m11"
#-----| -> call to puts
+# 139| End m11
+#-----| -> "End m11"
+
# 142| enter m12
#-----| -> b
From 799ec23b0d7ae0608de382acfe9b928a680d9c39 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 11:01:34 +0100
Subject: [PATCH 016/296] Ruby: Generalize `ExprChildMapping` logic to
`AstNode`s
---
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 36 +++++++++----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 369a79209ab..30e31833d84 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -132,7 +132,7 @@ class StringComponentCfgNode extends AstCfgNode {
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
-private Expr desugar(Expr n) {
+private AstNode desugar(AstNode n) {
result = n.getDesugared()
or
not exists(n.getDesugared()) and
@@ -147,10 +147,10 @@ abstract private class ExprChildMapping extends Expr {
* Holds if `child` is a (possibly nested) child of this expression
* for which we would like to find a matching CFG child.
*/
- abstract predicate relevantChild(Expr child);
+ abstract predicate relevantChild(AstNode child);
pragma[nomagic]
- private predicate reachesBasicBlock(Expr child, CfgNode cfn, BasicBlock bb) {
+ private predicate reachesBasicBlock(AstNode child, CfgNode cfn, BasicBlock bb) {
this.relevantChild(child) and
cfn = this.getAControlFlowNode() and
bb.getANode() = cfn
@@ -170,16 +170,16 @@ abstract private class ExprChildMapping extends Expr {
* The path never escapes the syntactic scope of this expression.
*/
cached
- predicate hasCfgChild(Expr child, CfgNode cfn, CfgNode cfnChild) {
+ predicate hasCfgChild(AstNode child, CfgNode cfn, CfgNode cfnChild) {
this.reachesBasicBlock(child, cfn, cfnChild.getBasicBlock()) and
- cfnChild = desugar(child).getAControlFlowNode()
+ cfnChild.getNode() = desugar(child)
}
}
/** Provides classes for control-flow nodes that wrap AST expressions. */
module ExprNodes {
private class LiteralChildMapping extends ExprChildMapping, Literal {
- override predicate relevantChild(Expr e) { none() }
+ override predicate relevantChild(AstNode n) { none() }
}
/** A control-flow node that wraps an `ArrayLiteral` AST expression. */
@@ -192,7 +192,7 @@ module ExprNodes {
}
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
- override predicate relevantChild(Expr e) { e = this.getAnOperand() }
+ override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
}
/** A control-flow node that wraps an `AssignExpr` AST expression. */
@@ -209,7 +209,7 @@ module ExprNodes {
}
private class OperationExprChildMapping extends ExprChildMapping, Operation {
- override predicate relevantChild(Expr e) { e = this.getAnOperand() }
+ override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
}
/** A control-flow node that wraps an `Operation` AST expression. */
@@ -292,7 +292,7 @@ module ExprNodes {
}
private class BlockArgumentChildMapping extends ExprChildMapping, BlockArgument {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = this.getValue() }
}
/** A control-flow node that wraps a `BlockArgument` AST expression. */
@@ -306,8 +306,8 @@ module ExprNodes {
}
private class CallExprChildMapping extends ExprChildMapping, Call {
- override predicate relevantChild(Expr e) {
- e = [this.getAnArgument(), this.(MethodCall).getReceiver(), this.(MethodCall).getBlock()]
+ override predicate relevantChild(AstNode n) {
+ n = [this.getAnArgument(), this.(MethodCall).getReceiver(), this.(MethodCall).getBlock()]
}
}
@@ -340,7 +340,7 @@ module ExprNodes {
}
private class CaseExprChildMapping extends ExprChildMapping, CaseExpr {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode e) { e = this.getValue() }
}
/** A control-flow node that wraps a `MethodCall` AST expression. */
@@ -361,7 +361,7 @@ module ExprNodes {
}
private class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
- override predicate relevantChild(Expr e) { e = this.getCondition() or e = this.getBranch(_) }
+ override predicate relevantChild(AstNode n) { n = [this.getCondition(), this.getBranch(_)] }
}
/** A control-flow node that wraps a `ConditionalExpr` AST expression. */
@@ -381,7 +381,7 @@ module ExprNodes {
}
private class ConstantAccessChildMapping extends ExprChildMapping, ConstantAccess {
- override predicate relevantChild(Expr e) { e = this.getScopeExpr() }
+ override predicate relevantChild(AstNode n) { n = this.getScopeExpr() }
}
/** A control-flow node that wraps a `ConditionalExpr` AST expression. */
@@ -397,7 +397,7 @@ module ExprNodes {
}
private class StmtSequenceChildMapping extends ExprChildMapping, StmtSequence {
- override predicate relevantChild(Expr e) { e = this.getLastStmt() }
+ override predicate relevantChild(AstNode n) { n = this.getLastStmt() }
}
/** A control-flow node that wraps a `StmtSequence` AST expression. */
@@ -411,7 +411,7 @@ module ExprNodes {
}
private class ForExprChildMapping extends ExprChildMapping, ForExpr {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = this.getValue() }
}
/** A control-flow node that wraps a `ForExpr` AST expression. */
@@ -430,7 +430,7 @@ module ExprNodes {
}
private class PairChildMapping extends ExprChildMapping, Pair {
- override predicate relevantChild(Expr e) { e = this.getKey() or e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = [this.getKey(), this.getValue()] }
}
/** A control-flow node that wraps a `Pair` AST expression. */
@@ -475,7 +475,7 @@ module ExprNodes {
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
- override predicate relevantChild(Expr e) { e = this.getComponent(_) }
+ override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
/** A control-flow node that wraps a `StringlikeLiteral` AST expression. */
From c3fd272f9b54c32e4d257c34fc0592173bb59b6a Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 11:03:07 +0100
Subject: [PATCH 017/296] Ruby: Simplify `getValueText` logic for
`StringlikeLiteral`s
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 21 +------------------
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 21 ++++---------------
.../test/library-tests/ast/ValueText.expected | 1 -
3 files changed, 5 insertions(+), 38 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 181c23fbf6e..1f5350bdb33 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -10,15 +10,7 @@ private import codeql.ruby.controlflow.CfgNodes
*
* This is the QL root class for all literals.
*/
-class Literal extends Expr, TLiteral {
- /**
- * Gets the source text for this literal, if this is a simple literal.
- *
- * For complex literals, such as arrays, hashes, and strings with
- * interpolations, this predicate has no result.
- */
- override string getValueText() { none() }
-}
+class Literal extends Expr, TLiteral { }
/**
* A numeric literal, i.e. an integer, floating-point, rational, or complex
@@ -411,17 +403,6 @@ class StringlikeLiteral extends Literal, TStringlikeLiteral {
result = ""
}
- override string getValueText() {
- forall(StringComponent c | c = this.getComponent(_) |
- not c instanceof StringInterpolationComponent
- ) and
- result =
- concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
- or
- exists(this.getComponent(_)) and
- result = this.getAControlFlowNode().(ExprNodes::StringlikeLiteralCfgNode).getValueText()
- }
-
override string toString() {
exists(string full, string summary |
full =
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 30e31833d84..8c35c4fc1b0 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -485,7 +485,7 @@ module ExprNodes {
final override StringlikeLiteral getExpr() { result = super.getExpr() }
/** Gets the `n`th component of this `StringlikeLiteral` */
- StringComponentCfgNode getComponent(int n) { result.getNode() = e.getComponent(n) }
+ StringComponentCfgNode getComponent(int n) { e.hasCfgChild(e.getComponent(n), this, result) }
/** Gets a component of this `StringlikeLiteral` */
StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
@@ -494,26 +494,13 @@ module ExprNodes {
// if all interpolations have a known string value, we will get a result
language[monotonicAggregates]
override string getValueText() {
- result = e.getValueText()
- or
result =
- concat(StringComponent c, int i |
- c = e.getComponent(i)
+ concat(StringComponentCfgNode c, int i |
+ c = this.getComponent(i)
|
- getComponentValueText(c) order by i
+ c.getValueText() order by i
)
}
-
- /**
- * Get the `ValueText()` of a `StringComponent`.
- * If the component has a CFG node, defer to that (in order to resolve variables in interpolations).
- * Otherwise, defer to the AST node.
- */
- private string getComponentValueText(StringComponent c) {
- exists(StringComponentCfgNode n | n.getNode() = c | result = n.getValueText())
- or
- not exists(StringComponentCfgNode n | n.getNode() = c) and result = c.getValueText()
- }
}
/** A control-flow node that wraps a `StringLiteral` AST expression. */
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index 57167453e7b..a456501c0c8 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -614,7 +614,6 @@
| modules/modules.rb:55:8:55:30 | "module Foo::Bar again" | module Foo::Bar again |
| modules/modules.rb:56:17:56:17 | 4 | 4 |
| modules/toplevel.rb:1:6:1:12 | "world" | world |
-| modules/toplevel.rb:3:12:3:16 | "!!!" | !!! |
| modules/toplevel.rb:5:14:5:20 | "hello" | hello |
| operations/operations.rb:3:5:3:5 | 0 | 0 |
| operations/operations.rb:4:5:4:5 | 0 | 0 |
From ac9cac78bc1705a99cd91a6ac02e7d3342a46179 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 21 Dec 2021 09:19:56 +0100
Subject: [PATCH 018/296] Ruby: Fix typo
---
.../codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index 22615dc2575..c56d1e6369d 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1350,8 +1350,8 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getComponent(i) }
}
- private class StringComponentComponentTree extends LeafTree, StringComponent {
- StringComponentComponentTree() { not this instanceof StringInterpolationComponent }
+ private class StringComponentTree extends LeafTree, StringComponent {
+ StringComponentTree() { not this instanceof StringInterpolationComponent }
}
private class ToplevelTree extends BodyStmtTree, Toplevel {
From 43ddc54f2b262317364b20b97a507a5a3f49a364 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Thu, 16 Dec 2021 13:24:31 +1300
Subject: [PATCH 019/296] Ruby: Add Module#const_get as a code execution
Module#const_get takes a single string argument and interprets it as the
name of a constant. It then looks up the constant and returns its value.
Object.const_get("Math::PI")
# => 3.141592653589793
By itself, this method is not as dangerous as e.g. eval, but if the
value returned is a class that is then instantiated, this can allow an
attacker to instantiate arbitrary Ruby classes.
As a result, I think it's safe to say that any remote input flowing into
this call is a potential vulnerability. A real-world example of this is
https://github.com/advisories/GHSA-52p9-v744-mwjj.
---
.../ruby/frameworks/StandardLibrary.qll | 12 +++++++++
.../frameworks/StandardLibrary.expected | 7 +++++
.../frameworks/StandardLibrary.ql | 4 +++
.../library-tests/frameworks/const_get.rb | 27 +++++++++++++++++++
.../security/cwe-094/CodeInjection.expected | 6 +++++
.../security/cwe-094/CodeInjection.rb | 13 +++++++++
6 files changed, 69 insertions(+)
create mode 100644 ruby/ql/test/library-tests/frameworks/const_get.rb
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll b/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
index ce8c443dda2..e66251e819c 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
@@ -335,6 +335,18 @@ class ModuleEvalCallCodeExecution extends CodeExecution::Range, DataFlow::CallNo
override DataFlow::Node getCode() { result = this.getArgument(0) }
}
+/**
+ * A call to `Module#const_get`, which interprets its argument as a Ruby constant.
+ * Passing user input to this method may result in instantiation of arbitrary Ruby classes.
+ */
+class ModuleConstGetCallCodeExecution extends CodeExecution::Range, DataFlow::CallNode {
+ ModuleConstGetCallCodeExecution() {
+ this.asExpr().getExpr().(UnknownMethodCall).getMethodName() = "const_get"
+ }
+
+ override DataFlow::Node getCode() { result = this.getArgument(0) }
+}
+
/** Flow summary for `Regexp.escape` and its alias, `Regexp.quote`. */
class RegexpEscapeSummary extends SummarizedCallable {
RegexpEscapeSummary() { this = "Regexp.escape" }
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
index 36fea1b31cd..9534a8be6de 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
@@ -93,3 +93,10 @@ loggerLoggingCallInputs
| Logging.rb:73:5:73:63 | call to log | Logging.rb:73:36:73:45 | "message1" |
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:36:74:45 | "message2" |
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:48:74:58 | "progname2" |
+moduleConstGetCallCodeExecutions
+| const_get.rb:1:1:1:24 | call to const_get | const_get.rb:1:18:1:23 | "Math" |
+| const_get.rb:2:1:2:28 | call to const_get | const_get.rb:2:22:2:27 | "Math" |
+| const_get.rb:3:1:3:20 | call to const_get | const_get.rb:3:16:3:19 | "PI" |
+| const_get.rb:4:1:4:19 | call to const_get | const_get.rb:4:16:4:18 | :PI |
+| const_get.rb:22:1:22:33 | call to const_get | const_get.rb:22:18:22:32 | "Foo::Baz::VAL" |
+| const_get.rb:23:1:23:25 | call to const_get | const_get.rb:23:15:23:24 | "Bar::VAL" |
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql b/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
index 2e6a62ba8fd..bb8102b68e4 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
@@ -32,3 +32,7 @@ query DataFlow::Node moduleEvalCallCodeExecutions(ModuleEvalCallCodeExecution e)
}
query DataFlow::Node loggerLoggingCallInputs(LoggerLoggingCall c) { result = c.getAnInput() }
+
+query DataFlow::Node moduleConstGetCallCodeExecutions(ModuleConstGetCallCodeExecution e) {
+ result = e.getCode()
+}
diff --git a/ruby/ql/test/library-tests/frameworks/const_get.rb b/ruby/ql/test/library-tests/frameworks/const_get.rb
new file mode 100644
index 00000000000..40b52ee0329
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/const_get.rb
@@ -0,0 +1,27 @@
+Object.const_get("Math")
+self.class.const_get("Math")
+Math.const_get("PI")
+Math.const_get(:PI)
+
+module Foo
+ class Bar
+ VAL = 10
+
+ def const_get(x)
+ "my custom const_get method"
+ end
+ end
+
+ class Baz < Bar
+ def self.const_get(x)
+ "another custom const_get method"
+ end
+ end
+end
+
+Object.const_get("Foo::Baz::VAL")
+Foo.const_get("Bar::VAL")
+
+# Should not be identified as a use of Module#const_get
+Foo::Bar.new.const_get 5
+Foo::Baz.const_get 5
\ No newline at end of file
diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
index f9e4dd35642..bcda3f9dc1e 100644
--- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
+++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
@@ -3,6 +3,8 @@ edges
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:6:10:6:13 | code |
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:18:20:18:23 | code |
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:21:21:21:24 | code |
+| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:27:15:27:18 | code |
+| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:30:19:30:22 | code |
nodes
| CodeInjection.rb:3:12:3:17 | call to params : | semmle.label | call to params : |
| CodeInjection.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : |
@@ -10,9 +12,13 @@ nodes
| CodeInjection.rb:9:10:9:15 | call to params | semmle.label | call to params |
| CodeInjection.rb:18:20:18:23 | code | semmle.label | code |
| CodeInjection.rb:21:21:21:24 | code | semmle.label | code |
+| CodeInjection.rb:27:15:27:18 | code | semmle.label | code |
+| CodeInjection.rb:30:19:30:22 | code | semmle.label | code |
subpaths
#select
| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on $@. | CodeInjection.rb:9:10:9:15 | call to params | a user-provided value |
| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
+| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
+| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
index 80ee5bee133..bee8357a9a5 100644
--- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
+++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
@@ -22,6 +22,15 @@ class UsersController < ActionController::Base
# GOOD
Bar.class_eval(code)
+
+ # BAD
+ const_get(code)
+
+ # BAD
+ Foo.const_get(code)
+
+ # GOOD
+ Bar.const_get(code)
end
def update
@@ -50,4 +59,8 @@ class Bar
def self.class_eval(x)
true
end
+
+ def self.const_get(x)
+ true
+ end
end
\ No newline at end of file
From 05b0daa0b73376810d9e92c58b18f6817c45333a Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 6 Jan 2022 14:14:42 +0800
Subject: [PATCH 020/296] Add the test of shutil module in FileSystemAccess.py
---
.../lib/semmle/python/frameworks/Stdlib.qll | 13 ++-------
.../frameworks/stdlib/FileSystemAccess.py | 28 +++++++++++++++++++
2 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
index 3f73793762f..dae470aee87 100644
--- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
@@ -2993,19 +2993,12 @@ private module StdlibPrivate {
}
}
- /**
- * A call to the `shutil.copyfileobj` function.
- *
- * See https://docs.python.org/3/library/shutil.html#shutil.copyfileobj
- */
+ // TODO: once we have flow summaries, model `shutil.copyfileobj` which copies the content between its' file-like arguments.
+ // See https://docs.python.org/3/library/shutil.html#shutil.copyfileobj
private class ShutilCopyfileobjCall extends FileSystemAccess::Range, DataFlow::CallCfgNode {
ShutilCopyfileobjCall() { this = shutil().getMember("copyfileobj").getACall() }
- override DataFlow::Node getAPathArgument() {
- result in [
- this.getArg(0), this.getArgByName("fsrc"), this.getArg(1), this.getArgByName("fdst")
- ]
- }
+ override DataFlow::Node getAPathArgument() { none() }
}
/**
diff --git a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
index 24459d2960b..ab9d4f5f252 100644
--- a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
+++ b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
@@ -3,6 +3,7 @@ import io
import os
import stat
import tempfile
+import shutil
open("file") # $ getAPathArgument="file"
open(file="file") # $ getAPathArgument="file"
@@ -238,3 +239,30 @@ tempfile.mkdtemp(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgume
tempfile.TemporaryDirectory("suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
tempfile.TemporaryDirectory(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
+
+shutil.rmtree("path") # $ getAPathArgument="path"
+shutil.rmtree(path="path") # $ getAPathArgument="path"
+
+shutil.copyfile("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copyfile(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.copy("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copy(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.copy2("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copy2(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.copytree("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copytree(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.move("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.move(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.copymode("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copymode(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.copystat("src", "dst") # $ getAPathArgument="src" getAPathArgument="dst"
+shutil.copystat(src="src", dst="dst") # $ getAPathArgument="src" getAPathArgument="dst"
+
+shutil.disk_usage("path") # $ getAPathArgument="path"
+shutil.disk_usage(path="path") # $ getAPathArgument="path"
\ No newline at end of file
From 759ec31508122cfe77411e2e3b4bbf6ceb417c2b Mon Sep 17 00:00:00 2001
From: haby0
Date: Thu, 6 Jan 2022 21:38:35 +0800
Subject: [PATCH 021/296] Delete shutil_path_injection.py file
---
.../frameworks/stdlib/FileSystemAccess.py | 4 +++
.../shutil_path_injection.py | 34 -------------------
2 files changed, 4 insertions(+), 34 deletions(-)
delete mode 100644 python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
diff --git a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
index ab9d4f5f252..5ac8b31ff68 100644
--- a/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
+++ b/python/ql/test/library-tests/frameworks/stdlib/FileSystemAccess.py
@@ -240,6 +240,10 @@ tempfile.mkdtemp(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgume
tempfile.TemporaryDirectory("suffix", "prefix", "dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
tempfile.TemporaryDirectory(suffix="suffix", prefix="prefix", dir="dir") # $ getAPathArgument="suffix" getAPathArgument="prefix" getAPathArgument="dir"
+# ------------------------------------------------------------------------------
+# shutil
+# ------------------------------------------------------------------------------
+
shutil.rmtree("path") # $ getAPathArgument="path"
shutil.rmtree(path="path") # $ getAPathArgument="path"
diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py b/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
deleted file mode 100644
index ca445cb6ed8..00000000000
--- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/shutil_path_injection.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import shutil
-from flask import Flask, request
-app = Flask(__name__)
-
-STATIC_DIR = "/server/static/"
-
-@app.route("/shutil-path1")
-def path_injection1():
- dir = request.args.get('dir', '')
- shutil.rmtree(dir) # NOT OK
-
-@app.route("/shutil-path2")
-def path_injection2():
- path1 = request.args.get('path1', '')
- path2 = request.args.get('path2', '')
- shutil.copyfile(path1, path2) # NOT OK
-
-@app.route("/shutil-path3")
-def path_injection3():
- path1 = request.args.get('path1', '')
- path2 = request.args.get('path2', '')
- shutil.copy(path1, path2) # NOT OK
-
-@app.route("/shutil-path4")
-def path_injection4():
- path1 = request.args.get('path1', '')
- path2 = request.args.get('path2', '')
- shutil.move(path1, path2) # NOT OK
-
-@app.route("/shutil-path4")
-def path_injection5():
- path1 = request.args.get('path1', '')
- path2 = request.args.get('path2', '')
- shutil.copymode(path1, path2) # NOT OK
\ No newline at end of file
From e4eb2c2a5980c4712b9391042d2d68135def4c9a Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Tue, 11 Jan 2022 15:21:12 -0800
Subject: [PATCH 022/296] Update docs on the output of `resolve qlpacks`
The output has changed and there are no more upgrades
packs. There are also other changes included here.
---
.../getting-started-with-the-codeql-cli.rst | 98 ++++++++++---------
1 file changed, 51 insertions(+), 47 deletions(-)
diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
index eaf47ec62f3..4651c6d1acd 100644
--- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
@@ -4,7 +4,7 @@ Getting started with the CodeQL CLI
===================================
To run CodeQL commands, you need to set up the CLI so that it can access
-the tools, queries, and libraries required to create and analyze databases.
+the tools, queries, and libraries required to create and analyze databases.
.. include:: ../reusables/license-note.rst
@@ -18,16 +18,16 @@ structures. To get started quickly, we recommend adopting a relatively simple
setup, as outlined in the steps below.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
-follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
-and 4 are slightly different---for further details, see the sections labeled
+follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
+and 4 are slightly different---for further details, see the sections labeled
**Information for macOS "Catalina" (or newer) users**. If you are using macOS
on Apple Silicon (e.g. Apple M1), ensure that the `Xcode command-line developer
tools `__ and `Rosetta 2
`__ are installed.
For information about installing the CodeQL CLI in a CI system to create results
-to display in GitHub as code scanning alerts, see
-`Installing CodeQL CLI in your CI system `__
+to display in GitHub as code scanning alerts, see
+`Installing CodeQL CLI in your CI system `__
in the GitHub documentation.
1. Download the CodeQL CLI zip package
@@ -42,9 +42,9 @@ Conditions `__.
There are several different versions of the CLI available to download, depending
on your use case:
-
+
- If you want to use the most up to date CodeQL tools and features, download the
- version tagged ``latest``.
+ version tagged ``latest``.
- If you want to create CodeQL databases to upload to LGTM Enterprise, download
the version that is compatible with the relevant LGTM Enterprise version
@@ -53,9 +53,9 @@ Conditions `__.
`__ on GitHub. Using the
correct version of the CLI ensures that your CodeQL databases are
compatible with your version of LGTM Enterprise. For more information,
- see `Preparing CodeQL databases to upload to LGTM
+ see `Preparing CodeQL databases to upload to LGTM
`__
- in the LGTM admin help.
+ in the LGTM admin help.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
`download the zip archive
@@ -72,12 +72,12 @@ Alternatively, you can download ``codeql.zip``, which contains the CLI for all s
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina" (or newer)
-
- If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
- version 12 ("Monterey"), you need to ensure that your web browser does not automatically
- extract zip files. If you use Safari, complete the following steps before downloading
+
+ If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
+ version 12 ("Monterey"), you need to ensure that your web browser does not automatically
+ extract zip files. If you use Safari, complete the following steps before downloading
the CodeQL CLI zip archive:
-
+
i. Open Safari.
ii. From the Safari menu, select **Preferences...**.
iii. Click the **General** Tab.
@@ -101,22 +101,22 @@ further options on the command line.
3. Obtain a local copy of the CodeQL queries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The `CodeQL repository `__ contains
+The `CodeQL repository `__ contains
the queries and libraries required for CodeQL analysis of C/C++, C#, Java,
JavaScript/TypeScript, Python, and Ruby.
-Clone a copy of this repository into ``codeql-home``.
-
-By default, the root of the cloned repository will be called ``codeql``.
-Rename this folder ``codeql-repo`` to avoid conflicting with the CodeQL
-CLI that you will extract in step 4. If you use git on the command line, you can
-clone and rename the repository in a single step by running
+Clone a copy of this repository into ``codeql-home``.
+
+By default, the root of the cloned repository will be called ``codeql``.
+Rename this folder ``codeql-repo`` to avoid conflicting with the CodeQL
+CLI that you will extract in step 4. If you use git on the command line, you can
+clone and rename the repository in a single step by running
``git clone git@github.com:github/codeql.git codeql-repo`` in the ``codeql-home`` folder.
The CodeQL libraries and queries for Go analysis live in the `CodeQL for Go
repository `__. Clone a copy of this
-repository into ``codeql-home``.
+repository into ``codeql-home``.
-The cloned repositories should have a sibling relationship.
+The cloned repositories should have a sibling relationship.
For example, if the root of the cloned CodeQL repository is
``$HOME/codeql-home/codeql-repo``, then the root of the cloned CodeQL for Go
repository should be ``$HOME/codeql-home/codeql-go``.
@@ -134,29 +134,29 @@ see ":doc:`About QL packs `."
- For the queries used on `LGTM.com `__, check out the
``lgtm.com`` branch. You should use this branch for databases you've built
using the CodeQL CLI, fetched from code scanning on GitHub, or recently downloaded from LGTM.com.
- The queries on the ``lgtm.com`` branch are more likely to be compatible
- with the ``latest`` CLI, so you'll be less likely to have to upgrade
- newly-created databases than if you use the ``main`` branch. Older databases
+ The queries on the ``lgtm.com`` branch are more likely to be compatible
+ with the ``latest`` CLI, so you'll be less likely to have to upgrade
+ newly-created databases than if you use the ``main`` branch. Older databases
may need to be upgraded before you can analyze them.
-
- - For the most up to date CodeQL queries, check out the ``main`` branch.
+
+ - For the most up to date CodeQL queries, check out the ``main`` branch.
This branch represents the very latest version of CodeQL's analysis. Even
databases created using the most recent version of the CLI may have to be
upgraded before you can analyze them. For more information, see
":doc:`Upgrading CodeQL databases `."
-
+
- For the queries used in a particular LGTM Enterprise release, check out the
branch tagged with the relevant release number. For example, the branch
tagged ``v1.27.0`` corresponds to LGTM Enterprise 1.27. You must use this
version if you want to upload data to LGTM Enterprise. For further
- information, see `Preparing CodeQL databases to upload to LGTM
+ information, see `Preparing CodeQL databases to upload to LGTM
`__
in the LGTM admin help.
4. Extract the zip archive
~~~~~~~~~~~~~~~~~~~~~~~~~~
-For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
+For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
simply
extract the zip archive into the directory you created in step 2.
@@ -171,16 +171,16 @@ For example, if the path to your copy of the CodeQL repository is
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina"
-
- macOS "Catalina", "Big Sur", or "Monterey" users should run the following
- commands in the Terminal, where ``${install_loc}`` is the path to the
+
+ macOS "Catalina", "Big Sur", or "Monterey" users should run the following
+ commands in the Terminal, where ``${install_loc}`` is the path to the
directory you created in step 2:
-
+
i. ``mv ~/Downloads/codeql*.zip ${install_loc}``
ii. ``cd ${install_loc}``
iii. ``/usr/bin/xattr -c codeql*.zip``
iv. ``unzip codeql*.zip``
-
+
5. Launch ``codeql``
~~~~~~~~~~~~~~~~~~~~
@@ -191,7 +191,7 @@ executable in a couple of ways:
```` is the folder where you extracted the CodeQL CLI
package.
- By adding ``/codeql`` to your ``PATH``, so that you
- can run the executable as just ``codeql``.
+ can run the executable as just ``codeql``.
At this point, you can execute CodeQL commands. For a full list of the CodeQL
CLI commands, see the "`CodeQL CLI manual <../manual>`__."
@@ -212,16 +212,20 @@ up to create and analyze databases:
- Run ``codeql resolve languages`` to show which languages are
available for database creation. This will list the languages supported by
- default in your CodeQL CLI package.
+ default in your CodeQL CLI package.
- Run ``codeql resolve qlpacks`` to show which QL packs the CLI can find. This
- will display the names of the QL packs included in the CodeQL repositories:
- ``codeql-cpp``, ``codeql-csharp``, ``codeql-go``,
- ``codeql-java``, ``codeql-javascript``, and ``codeql-python``. The CodeQL
- repositories also contain 'upgrade' packs and 'legacy' packs. Upgrade packs
- are used by the CLI when you want to upgrade a database so that it can be
- analyzed with a newer version of the CodeQL toolchain than was used to create
- it. Legacy packs ensure that custom queries and libraries created using older
- products are compatible with your version of CodeQL.
+ will display the names of all the QL packs directly available to the CodeQL CLI.
+ This should include:
+
+ - Query packs for each supported language, e.g., ``codeql/{language}-queries``.
+ These packs contain the standard queries that will be run for each analysis.
+ - Library packs for each supported language, e.g., ``codeql/{language}-all``. These
+ packs contain query libraries, such as control flow and data flow libraries, that
+ may be useful to other query authors.
+ - Example packs for each supported language, e.g., ``codeql/{language}-examples``.
+ These packs contain useful snippets of CodeQL that query auhtors may want To use.
+ - Legacy packs that ensure custom queries and libraries created using older products are
+ compatible with your version of CodeQL.
.. _using-two-versions-of-the-codeql-cli:
@@ -242,4 +246,4 @@ recommended directory setup depends on which versions you want to install:
directory. For example, if you unpack version 2.0.2 into
``$HOME/codeql-home/codeql-cli``, the older version should be
unpacked into ``$HOME/codeql-older-version/old-codeql-cli``. Here, the common
- grandparent is the ``$HOME`` directory.
+ grandparent is the ``$HOME`` directory.
From 263dbd33f6b908940e1b6d205652ccde050a35d6 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Wed, 12 Jan 2022 02:33:17 +0000
Subject: [PATCH 023/296] Optimize the query
---
.../CWE/CWE-552/UnsafeUrlForward.qhelp | 2 +-
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 127 ++++++++++--------
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 5 +-
.../CWE-552/UnsafeServletRequestDispatch.java | 2 +-
.../CWE-552/UnsafeUrlForward.expected | 12 --
5 files changed, 77 insertions(+), 71 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
index 8daef391db8..b8a3ddda77f 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
@@ -20,7 +20,7 @@ untrusted URL forwarding, it is recommended to avoid concatenating user input di
The following examples show the bad case and the good case respectively.
The bad methods show an HTTP request parameter being used directly in a URL forward
-without validating the input, which may cause file leakage. In good1 method,
+without validating the input, which may cause file leakage. In the good1 method,
ordinary forwarding requests are shown, which will not cause file leakage.
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index f77acf99e84..0bb939f66dd 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -18,16 +18,25 @@ import semmle.code.java.controlflow.Guards
import DataFlow::PathGraph
/**
- * Holds if `ma` is a method call of matching with a path string, probably a whitelisted one.
+ * Holds if `ma` is a call to a method that checks exact match of string, probably a whitelisted one.
*/
-predicate isStringPathMatch(MethodAccess ma) {
+predicate isExactStringPathMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().getName() = ["startsWith", "matches", "regionMatches"]
+ ma.getMethod().getName() = ["equals", "equalsIgnoreCase"]
}
/**
- * Holds if `ma` is a method call of `java.nio.file.Path` which matches with another
- * path, probably a whitelisted one.
+ * Holds if `ma` is a call to a method that checks a path string, probably a whitelisted one.
+ */
+predicate isStringPathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().getName() =
+ ["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
+}
+
+/**
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path, probably
+ * a whitelisted one.
*/
predicate isFilePathMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypePath and
@@ -35,7 +44,7 @@ predicate isFilePathMatch(MethodAccess ma) {
}
/**
- * Holds if `ma` is a method call that checks an input doesn't match using the `!`
+ * Holds if `ma` is a call to a method that checks an input doesn't match using the `!`
* logical negation expression.
*/
predicate checkNoPathMatch(MethodAccess ma) {
@@ -46,7 +55,7 @@ predicate checkNoPathMatch(MethodAccess ma) {
}
/**
- * Holds if `ma` is a method call to check special characters `..` used in path traversal.
+ * Holds if `ma` is a call to a method that checks special characters `..` used in path traversal.
*/
predicate isPathTraversalCheck(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
@@ -55,7 +64,7 @@ predicate isPathTraversalCheck(MethodAccess ma) {
}
/**
- * Holds if `ma` is a method call to decode a url string or check url encoding.
+ * Holds if `ma` is a call to a method that decodes a URL string or check URL encoding.
*/
predicate isPathDecoding(MethodAccess ma) {
// Search the special character `%` used in url encoding
@@ -68,44 +77,65 @@ predicate isPathDecoding(MethodAccess ma) {
ma.getMethod().hasName("decode")
}
-private class PathMatchSanitizer extends DataFlow::Node {
+/** The Java method `normalize` of `java.nio.file.Path`. */
+class PathNormalizeMethod extends Method {
+ PathNormalizeMethod() {
+ this.getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
+ this.hasName("normalize")
+ }
+}
+
+/**
+ * Sanitizer to check the following scenarios in a web application:
+ * 1. Exact string match
+ * 2. String startsWith or match check with path traversal validation
+ * 3. String not startsWith or not match check with decoding processing
+ * 4. java.nio.file.Path startsWith check having path normalization
+ */
+private class PathMatchSanitizer extends DataFlow::BarrierGuard {
PathMatchSanitizer() {
- exists(MethodAccess ma |
- (
- isStringPathMatch(ma) and
- exists(MethodAccess ma2 |
- isPathTraversalCheck(ma2) and
- ma.getQualifier().(VarAccess).getVariable().getAnAccess() = ma2.getQualifier()
- )
- or
- isFilePathMatch(ma)
- ) and
- (
- not checkNoPathMatch(ma)
- or
- // non-match check needs decoding e.g. !path.startsWith("/WEB-INF/") won't detect /%57EB-INF/web.xml, which will be decoded and served by RequestDispatcher
- checkNoPathMatch(ma) and
- exists(MethodAccess ma2 |
- isPathDecoding(ma2) and
- ma.getQualifier().(VarAccess).getVariable().getAnAccess() = ma2.getQualifier()
- )
- ) and
- this.asExpr() = ma.getQualifier()
+ isExactStringPathMatch(this)
+ or
+ isStringPathMatch(this) and
+ not checkNoPathMatch(this) and
+ exists(MethodAccess tma |
+ isPathTraversalCheck(tma) and
+ DataFlow::localExprFlow(this.(MethodAccess).getQualifier(), tma.getQualifier())
+ )
+ or
+ checkNoPathMatch(this) and
+ exists(MethodAccess dma |
+ isPathDecoding(dma) and
+ DataFlow::localExprFlow(dma, this.(MethodAccess).getQualifier())
+ )
+ or
+ isFilePathMatch(this) and
+ exists(MethodAccess pma |
+ pma.getMethod() instanceof PathNormalizeMethod and
+ DataFlow::localExprFlow(pma, this.(MethodAccess).getQualifier())
+ )
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and
+ (
+ branch = true and not checkNoPathMatch(this)
+ or
+ branch = false and checkNoPathMatch(this)
)
}
}
/**
- * Holds if `ma` is a method call to check string content, which means an input string is not
+ * Holds if `ma` is a call to a method that checks string content, which means an input string is not
* blindly trusted and helps to reduce FPs.
*/
predicate checkStringContent(MethodAccess ma, Expr expr) {
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod()
.hasName([
- "charAt", "contains", "equals", "equalsIgnoreCase", "getBytes", "getChars", "indexOf",
- "lastIndexOf", "length", "matches", "regionMatches", "replace", "replaceAll",
- "replaceFirst", "substring"
+ "charAt", "getBytes", "getChars", "length", "replace", "replaceAll", "replaceFirst",
+ "substring"
]) and
expr = ma.getQualifier()
or
@@ -145,23 +175,6 @@ private class NullOrEmptyCheckSanitizer extends DataFlow::Node {
NullOrEmptyCheckSanitizer() { isNullOrEmptyCheck(this.asExpr()) }
}
-/** Holds if `ma` is a virtual method call of Map::get or Object::toString. */
-predicate isVirtualMethod(MethodAccess ma, Expr expr) {
- ma.getMethod().getDeclaringType() instanceof TypeObject and
- ma.getMethod().hasName("toString") and
- (expr = ma or expr = ma.getQualifier())
- or
- (
- ma.getMethod().getDeclaringType().getASupertype*().hasQualifiedName("java.util", "Map") and
- ma.getMethod().hasName(["get", "getOrDefault"])
- ) and
- (expr = ma or expr = ma.getAnArgument())
-}
-
-private class VirtualMethodSanitizer extends DataFlow::Node {
- VirtualMethodSanitizer() { exists(MethodAccess ma | isVirtualMethod(ma, this.asExpr())) }
-}
-
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
@@ -181,10 +194,16 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) {
node instanceof UnsafeUrlForwardSanitizer or
- node instanceof PathMatchSanitizer or
node instanceof StringOperationSanitizer or
- node instanceof NullOrEmptyCheckSanitizer or
- node instanceof VirtualMethodSanitizer
+ node instanceof NullOrEmptyCheckSanitizer
+ }
+
+ override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
+ guard instanceof PathMatchSanitizer
+ }
+
+ override DataFlow::FlowFeature getAFeature() {
+ result instanceof DataFlow::FeatureHasSourceCallContext
}
}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index ab15549b9e1..cb70dffbafc 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -87,10 +87,9 @@ private class FilePathFlowStep extends SummaryModelCsv {
override predicate row(string row) {
row =
[
- "java.nio.file;Paths;true;get;;;Argument[-1];ReturnValue;taint",
- "java.nio.file;Path;true;resolve;;;Argument[0];ReturnValue;taint",
+ "java.nio.file;Paths;true;get;;;Argument[0..1];ReturnValue;taint",
+ "java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint",
"java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint",
- "java.nio.file;Path;true;startsWith;;;Argument[-1];ReturnValue;taint",
"java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint"
]
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
index f0b0a71ea0f..b79db0fc6e6 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
@@ -100,7 +100,7 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
}
}
- // BAD: Request dispatcher with improper negation check and without url decoding
+ // GOOD: Request dispatcher with negation check and path normalization
protected void doHead5(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getParameter("path");
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
index 185508dfc57..d3f8fc247d2 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
@@ -3,11 +3,6 @@ edges
| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL |
| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path |
-| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:107:53:107:56 | path : String |
-| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path |
-| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path |
-| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path |
-| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url |
| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url |
@@ -25,12 +20,6 @@ nodes
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | semmle.label | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | semmle.label | path |
-| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
-| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | semmle.label | resolve(...) : Path |
-| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | semmle.label | normalize(...) : Path |
-| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | semmle.label | path : String |
-| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | semmle.label | requestedPath : Path |
-| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | semmle.label | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String |
@@ -52,7 +41,6 @@ subpaths
| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) | user-provided value |
-| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) | user-provided value |
| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value |
| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value |
| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value |
From cd9a485c47a9ae8c4145fffaaba8e4bc435bdfdf Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Thu, 13 Jan 2022 14:44:08 +0100
Subject: [PATCH 024/296] Refactor NullOrEmptyCheckGuard
---
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 49 +++++++++----------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index 0bb939f66dd..c43b48e7621 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -15,6 +15,7 @@ import UnsafeUrlForward
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets
import semmle.code.java.controlflow.Guards
+import semmle.code.java.dataflow.NullGuards
import DataFlow::PathGraph
/**
@@ -92,8 +93,8 @@ class PathNormalizeMethod extends Method {
* 3. String not startsWith or not match check with decoding processing
* 4. java.nio.file.Path startsWith check having path normalization
*/
-private class PathMatchSanitizer extends DataFlow::BarrierGuard {
- PathMatchSanitizer() {
+private class PathMatchGuard extends DataFlow::BarrierGuard {
+ PathMatchGuard() {
isExactStringPathMatch(this)
or
isStringPathMatch(this) and
@@ -150,29 +151,25 @@ private class StringOperationSanitizer extends DataFlow::Node {
StringOperationSanitizer() { exists(MethodAccess ma | checkStringContent(ma, this.asExpr())) }
}
-/**
- * Holds if `expr` is an expression returned from null or empty string check.
- */
-predicate isNullOrEmptyCheck(Expr expr) {
- exists(ConditionBlock cb, ReturnStmt rt |
- cb.controls(rt.getBasicBlock(), true) and
- (
- cb.getCondition().(EQExpr).getAnOperand() instanceof NullLiteral // if (path == null)
- or
- // if (path.equals(""))
- exists(MethodAccess ma |
+private class NullOrEmptyCheckGuard extends DataFlow::BarrierGuard {
+ NullOrEmptyCheckGuard() {
+ this = nullGuard(_, _, _)
+ or
+ exists(MethodAccess ma |
cb.getCondition() = ma and
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName("equals") and
- ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = ""
- )
- ) and
- expr.getParent+() = rt
- )
-}
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName("equals") and
+ ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "" and
+ this = ma
+ )
+ }
-private class NullOrEmptyCheckSanitizer extends DataFlow::Node {
- NullOrEmptyCheckSanitizer() { isNullOrEmptyCheck(this.asExpr()) }
+ override predicate checks(Expr e, boolean branch) {
+ exists(SsaVariable ssa | this = nullGuard(ssa, branch, true) and e = ssa.getAFirstUse())
+ or
+ e = this.(MethodAccess).getQualifier() and
+ branch = true
+ }
}
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
@@ -194,12 +191,12 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) {
node instanceof UnsafeUrlForwardSanitizer or
- node instanceof StringOperationSanitizer or
- node instanceof NullOrEmptyCheckSanitizer
+ node instanceof StringOperationSanitizer
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
- guard instanceof PathMatchSanitizer
+ guard instanceof PathMatchGuard or
+ guard instanceof NullOrEmptyCheckGuard
}
override DataFlow::FlowFeature getAFeature() {
From 81feaaec0270c7b9635d539eaa7f3877d34e9340 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Thu, 13 Jan 2022 15:03:31 +0100
Subject: [PATCH 025/296] Refactor PathMatchGuard
---
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 156 +++++++-----------
.../CWE-552/UnsafeServletRequestDispatch.java | 6 +-
.../CWE-552/UnsafeUrlForward.expected | 12 ++
3 files changed, 72 insertions(+), 102 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index c43b48e7621..89baadd5388 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -19,7 +19,7 @@ import semmle.code.java.dataflow.NullGuards
import DataFlow::PathGraph
/**
- * Holds if `ma` is a call to a method that checks exact match of string, probably a whitelisted one.
+ * Holds if `ma` is a call to a method that checks exact match of string.
*/
predicate isExactStringPathMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
@@ -27,7 +27,7 @@ predicate isExactStringPathMatch(MethodAccess ma) {
}
/**
- * Holds if `ma` is a call to a method that checks a path string, probably a whitelisted one.
+ * Holds if `ma` is a call to a method that checks a path string.
*/
predicate isStringPathMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
@@ -36,8 +36,7 @@ predicate isStringPathMatch(MethodAccess ma) {
}
/**
- * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path, probably
- * a whitelisted one.
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
*/
predicate isFilePathMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypePath and
@@ -45,37 +44,36 @@ predicate isFilePathMatch(MethodAccess ma) {
}
/**
- * Holds if `ma` is a call to a method that checks an input doesn't match using the `!`
- * logical negation expression.
+ * Holds if `ma` protects against path traversal, by either:
+ * * looking for the literal `..`
+ * * performing path normalization
*/
-predicate checkNoPathMatch(MethodAccess ma) {
- exists(LogNotExpr lne |
- (isStringPathMatch(ma) or isFilePathMatch(ma)) and
- lne.getExpr() = ma
- )
-}
-
-/**
- * Holds if `ma` is a call to a method that checks special characters `..` used in path traversal.
- */
-predicate isPathTraversalCheck(MethodAccess ma) {
+predicate isPathTraversalCheck(MethodAccess ma, Expr checked) {
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
+ ma.(Guard).controls(checked.getBasicBlock(), false)
+ or
+ ma.getMethod() instanceof PathNormalizeMethod and
+ checked = ma
}
/**
- * Holds if `ma` is a call to a method that decodes a URL string or check URL encoding.
+ * Holds if `ma` protects against double URL encoding, by either:
+ * * looking for the literal `%`
+ * * performing URL decoding
*/
-predicate isPathDecoding(MethodAccess ma) {
+predicate isURLEncodingCheck(MethodAccess ma, Expr checked) {
// Search the special character `%` used in url encoding
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
+ ma.(Guard).controls(checked.getBasicBlock(), false)
or
// Call to `URLDecoder` assuming the implementation handles double encoding correctly
ma.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
- ma.getMethod().hasName("decode")
+ ma.getMethod().hasName("decode") and
+ checked = ma
}
/** The Java method `normalize` of `java.nio.file.Path`. */
@@ -86,92 +84,56 @@ class PathNormalizeMethod extends Method {
}
}
+private predicate isDisallowedWord(CompileTimeConstantExpr word) {
+ word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
+}
+
+private predicate isAllowListCheck(MethodAccess ma) {
+ (isStringPathMatch(ma) or isFilePathMatch(ma)) and
+ not isDisallowedWord(ma.getAnArgument())
+}
+
+private predicate isDisallowListCheck(MethodAccess ma) {
+ (isStringPathMatch(ma) or isFilePathMatch(ma)) and
+ isDisallowedWord(ma.getAnArgument())
+}
+
/**
- * Sanitizer to check the following scenarios in a web application:
+ * A guard that checks a path with the following methods:
* 1. Exact string match
- * 2. String startsWith or match check with path traversal validation
- * 3. String not startsWith or not match check with decoding processing
- * 4. java.nio.file.Path startsWith check having path normalization
+ * 2. Path matches allowed values (needs to protect against path traversal)
+ * 3. Path matches disallowed values (needs to protect against URL encoding)
*/
private class PathMatchGuard extends DataFlow::BarrierGuard {
PathMatchGuard() {
- isExactStringPathMatch(this)
- or
- isStringPathMatch(this) and
- not checkNoPathMatch(this) and
- exists(MethodAccess tma |
- isPathTraversalCheck(tma) and
- DataFlow::localExprFlow(this.(MethodAccess).getQualifier(), tma.getQualifier())
- )
- or
- checkNoPathMatch(this) and
- exists(MethodAccess dma |
- isPathDecoding(dma) and
- DataFlow::localExprFlow(dma, this.(MethodAccess).getQualifier())
- )
- or
- isFilePathMatch(this) and
- exists(MethodAccess pma |
- pma.getMethod() instanceof PathNormalizeMethod and
- DataFlow::localExprFlow(pma, this.(MethodAccess).getQualifier())
- )
+ isExactStringPathMatch(this) or isStringPathMatch(this) or isFilePathMatch(this)
}
override predicate checks(Expr e, boolean branch) {
e = this.(MethodAccess).getQualifier() and
(
- branch = true and not checkNoPathMatch(this)
+ isExactStringPathMatch(this) and
+ branch = true
or
- branch = false and checkNoPathMatch(this)
+ isAllowListCheck(this) and
+ exists(MethodAccess ma, Expr checked | isPathTraversalCheck(ma, checked) |
+ DataFlow::localExprFlow(checked, e)
+ or
+ ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ ) and
+ branch = true
+ or
+ isDisallowListCheck(this) and
+ exists(MethodAccess ma, Expr checked | isURLEncodingCheck(ma, checked) |
+ DataFlow::localExprFlow(checked, e)
+ or
+ ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ ) and
+ branch = false
)
}
}
-/**
- * Holds if `ma` is a call to a method that checks string content, which means an input string is not
- * blindly trusted and helps to reduce FPs.
- */
-predicate checkStringContent(MethodAccess ma, Expr expr) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod()
- .hasName([
- "charAt", "getBytes", "getChars", "length", "replace", "replaceAll", "replaceFirst",
- "substring"
- ]) and
- expr = ma.getQualifier()
- or
- (
- ma.getMethod().getDeclaringType() instanceof TypeStringBuffer or
- ma.getMethod().getDeclaringType() instanceof TypeStringBuilder
- ) and
- expr = ma.getAnArgument()
-}
-
-private class StringOperationSanitizer extends DataFlow::Node {
- StringOperationSanitizer() { exists(MethodAccess ma | checkStringContent(ma, this.asExpr())) }
-}
-
-private class NullOrEmptyCheckGuard extends DataFlow::BarrierGuard {
- NullOrEmptyCheckGuard() {
- this = nullGuard(_, _, _)
- or
- exists(MethodAccess ma |
- cb.getCondition() = ma and
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName("equals") and
- ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "" and
- this = ma
- )
- }
-
- override predicate checks(Expr e, boolean branch) {
- exists(SsaVariable ssa | this = nullGuard(ssa, branch, true) and e = ssa.getAFirstUse())
- or
- e = this.(MethodAccess).getQualifier() and
- branch = true
- }
-}
-
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
@@ -189,14 +151,10 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeUrlForwardSink }
- override predicate isSanitizer(DataFlow::Node node) {
- node instanceof UnsafeUrlForwardSanitizer or
- node instanceof StringOperationSanitizer
- }
+ override predicate isSanitizer(DataFlow::Node node) { node instanceof UnsafeUrlForwardSanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
- guard instanceof PathMatchGuard or
- guard instanceof NullOrEmptyCheckGuard
+ guard instanceof PathMatchGuard
}
override DataFlow::FlowFeature getAFeature() {
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
index b79db0fc6e6..279764fba8b 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeServletRequestDispatch.java
@@ -80,7 +80,7 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
// GOOD: Request dispatcher with path traversal check
protected void doHead3(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
- String path = request.getParameter("path");
+ String path = request.getParameter("path");
if (path.startsWith(BASE_PATH) && !path.contains("..")) {
request.getServletContext().getRequestDispatcher(path).include(request, response);
@@ -100,7 +100,7 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
}
}
- // GOOD: Request dispatcher with negation check and path normalization
+ // BAD: Request dispatcher with negation check and path normalization, but without URL decoding
protected void doHead5(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getParameter("path");
@@ -111,7 +111,7 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
}
}
- // GOOD: Request dispatcher with path traversal check and url decoding
+ // GOOD: Request dispatcher with path traversal check and URL decoding
protected void doHead6(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getParameter("path");
diff --git a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
index d3f8fc247d2..185508dfc57 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-552/UnsafeUrlForward.expected
@@ -3,6 +3,11 @@ edges
| UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL |
| UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:107:53:107:56 | path : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url |
| UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url |
@@ -20,6 +25,12 @@ nodes
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | semmle.label | returnURL |
| UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | semmle.label | path |
+| UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
+| UnsafeServletRequestDispatch.java:107:24:107:57 | resolve(...) : Path | semmle.label | resolve(...) : Path |
+| UnsafeServletRequestDispatch.java:107:24:107:69 | normalize(...) : Path | semmle.label | normalize(...) : Path |
+| UnsafeServletRequestDispatch.java:107:53:107:56 | path : String | semmle.label | path : String |
+| UnsafeServletRequestDispatch.java:110:53:110:65 | requestedPath : Path | semmle.label | requestedPath : Path |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | semmle.label | toString(...) |
| UnsafeUrlForward.java:13:27:13:36 | url : String | semmle.label | url : String |
| UnsafeUrlForward.java:14:27:14:29 | url | semmle.label | url |
| UnsafeUrlForward.java:18:27:18:36 | url : String | semmle.label | url : String |
@@ -41,6 +52,7 @@ subpaths
| UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:32:51:32:59 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:23:22:23:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) : String | UnsafeServletRequestDispatch.java:48:56:48:64 | returnURL | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:42:22:42:54 | getParameter(...) | user-provided value |
| UnsafeServletRequestDispatch.java:76:53:76:56 | path | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:76:53:76:56 | path | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:71:17:71:44 | getParameter(...) | user-provided value |
+| UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) : String | UnsafeServletRequestDispatch.java:110:53:110:76 | toString(...) | Potentially untrusted URL forward due to $@. | UnsafeServletRequestDispatch.java:106:17:106:44 | getParameter(...) | user-provided value |
| UnsafeUrlForward.java:14:27:14:29 | url | UnsafeUrlForward.java:13:27:13:36 | url : String | UnsafeUrlForward.java:14:27:14:29 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:13:27:13:36 | url | user-provided value |
| UnsafeUrlForward.java:20:28:20:30 | url | UnsafeUrlForward.java:18:27:18:36 | url : String | UnsafeUrlForward.java:20:28:20:30 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:18:27:18:36 | url | user-provided value |
| UnsafeUrlForward.java:26:23:26:25 | url | UnsafeUrlForward.java:25:21:25:30 | url : String | UnsafeUrlForward.java:26:23:26:25 | url | Potentially untrusted URL forward due to $@. | UnsafeUrlForward.java:25:21:25:30 | url | user-provided value |
From b6886b8e4385f5857f62d27395d85d1ee2fe4227 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Thu, 13 Jan 2022 15:28:57 +0100
Subject: [PATCH 026/296] Move code to qll file
---
.../Security/CWE/CWE-552/UnsafeUrlForward.ql | 123 +-----------------
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 120 +++++++++++++++++
2 files changed, 122 insertions(+), 121 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
index 89baadd5388..a39076f89c1 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.ql
@@ -1,5 +1,5 @@
/**
- * @name Unsafe url forward or dispatch from remote source
+ * @name Unsafe URL forward or dispatch from remote source
* @description URL forward or dispatch based on unvalidated user-input
* may cause file information disclosure.
* @kind path-problem
@@ -13,127 +13,8 @@
import java
import UnsafeUrlForward
import semmle.code.java.dataflow.FlowSources
-import semmle.code.java.frameworks.Servlets
-import semmle.code.java.controlflow.Guards
-import semmle.code.java.dataflow.NullGuards
import DataFlow::PathGraph
-/**
- * Holds if `ma` is a call to a method that checks exact match of string.
- */
-predicate isExactStringPathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().getName() = ["equals", "equalsIgnoreCase"]
-}
-
-/**
- * Holds if `ma` is a call to a method that checks a path string.
- */
-predicate isStringPathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().getName() =
- ["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
-}
-
-/**
- * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
- */
-predicate isFilePathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypePath and
- ma.getMethod().getName() = "startsWith"
-}
-
-/**
- * Holds if `ma` protects against path traversal, by either:
- * * looking for the literal `..`
- * * performing path normalization
- */
-predicate isPathTraversalCheck(MethodAccess ma, Expr checked) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
- ma.(Guard).controls(checked.getBasicBlock(), false)
- or
- ma.getMethod() instanceof PathNormalizeMethod and
- checked = ma
-}
-
-/**
- * Holds if `ma` protects against double URL encoding, by either:
- * * looking for the literal `%`
- * * performing URL decoding
- */
-predicate isURLEncodingCheck(MethodAccess ma, Expr checked) {
- // Search the special character `%` used in url encoding
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
- ma.(Guard).controls(checked.getBasicBlock(), false)
- or
- // Call to `URLDecoder` assuming the implementation handles double encoding correctly
- ma.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
- ma.getMethod().hasName("decode") and
- checked = ma
-}
-
-/** The Java method `normalize` of `java.nio.file.Path`. */
-class PathNormalizeMethod extends Method {
- PathNormalizeMethod() {
- this.getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
- this.hasName("normalize")
- }
-}
-
-private predicate isDisallowedWord(CompileTimeConstantExpr word) {
- word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
-}
-
-private predicate isAllowListCheck(MethodAccess ma) {
- (isStringPathMatch(ma) or isFilePathMatch(ma)) and
- not isDisallowedWord(ma.getAnArgument())
-}
-
-private predicate isDisallowListCheck(MethodAccess ma) {
- (isStringPathMatch(ma) or isFilePathMatch(ma)) and
- isDisallowedWord(ma.getAnArgument())
-}
-
-/**
- * A guard that checks a path with the following methods:
- * 1. Exact string match
- * 2. Path matches allowed values (needs to protect against path traversal)
- * 3. Path matches disallowed values (needs to protect against URL encoding)
- */
-private class PathMatchGuard extends DataFlow::BarrierGuard {
- PathMatchGuard() {
- isExactStringPathMatch(this) or isStringPathMatch(this) or isFilePathMatch(this)
- }
-
- override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and
- (
- isExactStringPathMatch(this) and
- branch = true
- or
- isAllowListCheck(this) and
- exists(MethodAccess ma, Expr checked | isPathTraversalCheck(ma, checked) |
- DataFlow::localExprFlow(checked, e)
- or
- ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
- ) and
- branch = true
- or
- isDisallowListCheck(this) and
- exists(MethodAccess ma, Expr checked | isURLEncodingCheck(ma, checked) |
- DataFlow::localExprFlow(checked, e)
- or
- ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
- ) and
- branch = false
- )
- }
-}
-
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
UnsafeUrlForwardFlowConfig() { this = "UnsafeUrlForwardFlowConfig" }
@@ -154,7 +35,7 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof UnsafeUrlForwardSanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
- guard instanceof PathMatchGuard
+ guard instanceof UnsafeUrlForwardBarrierGuard
}
override DataFlow::FlowFeature getAFeature() {
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index cb70dffbafc..3979e8dd96d 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -1,5 +1,6 @@
import java
import DataFlow
+import semmle.code.java.controlflow.Guards
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets
import semmle.code.java.frameworks.spring.SpringWeb
@@ -30,6 +31,125 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
FollowsSanitizingPrefix() { this.asExpr() = any(SanitizingPrefix fp).getAnAppendedExpression() }
}
+/** A barrier guard that protects against URL forward vulnerabilities. */
+abstract class UnsafeUrlForwardBarrierGuard extends DataFlow::BarrierGuard { }
+
+/**
+ * Holds if `ma` is a call to a method that checks exact match of string.
+ */
+private predicate isExactStringPathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().getName() = ["equals", "equalsIgnoreCase"]
+}
+
+/**
+ * Holds if `ma` is a call to a method that checks a path string.
+ */
+private predicate isStringPathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().getName() =
+ ["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
+}
+
+/**
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
+ */
+private predicate isFilePathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypePath and
+ ma.getMethod().getName() = "startsWith"
+}
+
+/**
+ * Holds if `ma` protects against path traversal, by either:
+ * * looking for the literal `..`
+ * * performing path normalization
+ */
+private predicate isPathTraversalCheck(MethodAccess ma, Expr checked) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName(["contains", "indexOf"]) and
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
+ ma.(Guard).controls(checked.getBasicBlock(), false)
+ or
+ ma.getMethod() instanceof PathNormalizeMethod and
+ checked = ma
+}
+
+/**
+ * Holds if `ma` protects against double URL encoding, by either:
+ * * looking for the literal `%`
+ * * performing URL decoding
+ */
+private predicate isURLEncodingCheck(MethodAccess ma, Expr checked) {
+ // Search the special character `%` used in url encoding
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().hasName(["contains", "indexOf"]) and
+ ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
+ ma.(Guard).controls(checked.getBasicBlock(), false)
+ or
+ // Call to `URLDecoder` assuming the implementation handles double encoding correctly
+ ma.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
+ ma.getMethod().hasName("decode") and
+ checked = ma
+}
+
+/** The Java method `normalize` of `java.nio.file.Path`. */
+private class PathNormalizeMethod extends Method {
+ PathNormalizeMethod() {
+ this.getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
+ this.hasName("normalize")
+ }
+}
+
+private predicate isDisallowedWord(CompileTimeConstantExpr word) {
+ word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
+}
+
+private predicate isAllowListCheck(MethodAccess ma) {
+ (isStringPathMatch(ma) or isFilePathMatch(ma)) and
+ not isDisallowedWord(ma.getAnArgument())
+}
+
+private predicate isDisallowListCheck(MethodAccess ma) {
+ (isStringPathMatch(ma) or isFilePathMatch(ma)) and
+ isDisallowedWord(ma.getAnArgument())
+}
+
+/**
+ * A guard that checks a path with the following methods:
+ * 1. Exact string match
+ * 2. Path matches allowed values (needs to protect against path traversal)
+ * 3. Path matches disallowed values (needs to protect against URL encoding)
+ */
+private class PathMatchGuard extends UnsafeUrlForwardBarrierGuard {
+ PathMatchGuard() {
+ isExactStringPathMatch(this) or isStringPathMatch(this) or isFilePathMatch(this)
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and
+ (
+ isExactStringPathMatch(this) and
+ branch = true
+ or
+ isAllowListCheck(this) and
+ exists(MethodAccess ma, Expr checked | isPathTraversalCheck(ma, checked) |
+ DataFlow::localExprFlow(checked, e)
+ or
+ ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ ) and
+ branch = true
+ or
+ isDisallowListCheck(this) and
+ exists(MethodAccess ma, Expr checked | isURLEncodingCheck(ma, checked) |
+ DataFlow::localExprFlow(checked, e)
+ or
+ ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ ) and
+ branch = false
+ )
+ }
+}
+
abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
/** An argument to `getRequestDispatcher`. */
From c6deccf863354377bb7d40143b05ab450be3bc05 Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Thu, 13 Jan 2022 09:02:10 -0800
Subject: [PATCH 027/296] Minor fixes to the getting started docs
Co-authored-by: Felicity Chapman
---
.../codeql-cli/getting-started-with-the-codeql-cli.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
index 4651c6d1acd..3c91fc75209 100644
--- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
@@ -217,13 +217,13 @@ up to create and analyze databases:
will display the names of all the QL packs directly available to the CodeQL CLI.
This should include:
- - Query packs for each supported language, e.g., ``codeql/{language}-queries``.
+ - Query packs for each supported language, for example, ``codeql/{language}-queries``.
These packs contain the standard queries that will be run for each analysis.
- - Library packs for each supported language, e.g., ``codeql/{language}-all``. These
+ - Library packs for each supported language, for example, ``codeql/{language}-all``. These
packs contain query libraries, such as control flow and data flow libraries, that
- may be useful to other query authors.
- - Example packs for each supported language, e.g., ``codeql/{language}-examples``.
- These packs contain useful snippets of CodeQL that query auhtors may want To use.
+ may be useful to query writers.
+ - Example packs for each supported language, for example, ``codeql/{language}-examples``.
+ These packs contain useful snippets of CodeQL that query writers may find useful.
- Legacy packs that ensure custom queries and libraries created using older products are
compatible with your version of CodeQL.
From 877c52981ff3b333d13cdb802b7f3592e5d753bc Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Fri, 14 Jan 2022 12:13:41 +0000
Subject: [PATCH 028/296] Remove the deprecated library keyword
---
java/ql/lib/semmle/code/java/frameworks/Servlets.qll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
index 2ab2c62c4d4..d9988e31f67 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll
@@ -349,7 +349,7 @@ predicate isRequestGetParamMethod(MethodAccess ma) {
}
/** The Java EE RequestDispatcher. */
-library class RequestDispatcher extends RefType {
+class RequestDispatcher extends RefType {
RequestDispatcher() {
this.hasQualifiedName(["javax.servlet", "jakarta.servlet"], "RequestDispatcher") or
this.hasQualifiedName("javax.portlet", "PortletRequestDispatcher")
@@ -357,7 +357,7 @@ library class RequestDispatcher extends RefType {
}
/** The `getRequestDispatcher` method. */
-library class GetRequestDispatcherMethod extends Method {
+class GetRequestDispatcherMethod extends Method {
GetRequestDispatcherMethod() {
this.getReturnType() instanceof RequestDispatcher and
this.getName() = "getRequestDispatcher"
@@ -365,7 +365,7 @@ library class GetRequestDispatcherMethod extends Method {
}
/** The request dispatch method. */
-library class RequestDispatchMethod extends Method {
+class RequestDispatchMethod extends Method {
RequestDispatchMethod() {
this.getDeclaringType() instanceof RequestDispatcher and
this.hasName(["forward", "include"])
From 136fefbab55fe4ec9f2cec51feeddbf2c37ec9fa Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Fri, 14 Jan 2022 13:38:17 +0100
Subject: [PATCH 029/296] Apply suggestions from code review
Co-authored-by: Chris Smowton
---
.../src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 3979e8dd96d..9d7272ea9fe 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -122,7 +122,7 @@ private predicate isDisallowListCheck(MethodAccess ma) {
*/
private class PathMatchGuard extends UnsafeUrlForwardBarrierGuard {
PathMatchGuard() {
- isExactStringPathMatch(this) or isStringPathMatch(this) or isFilePathMatch(this)
+ isExactStringPathMatch(this) or isAllowListCheck(this) or isDisallowListCheck(this)
}
override predicate checks(Expr e, boolean branch) {
From fb1287d577d09cfd6710b51c466351e47fd624c4 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Fri, 14 Jan 2022 15:20:41 +0100
Subject: [PATCH 030/296] Use dominance instead of getParent
Add clarification comments to PathMatchGuard
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 24 ++++++++++++++-----
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 9d7272ea9fe..119670cdd14 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -131,19 +131,31 @@ private class PathMatchGuard extends UnsafeUrlForwardBarrierGuard {
isExactStringPathMatch(this) and
branch = true
or
+ // When using an allowlist, that is, checking for known safe paths
+ // (for example, `path.startsWith(BASE_PATH)`)
+ // the application needs to protect against path traversal bypasses.
isAllowListCheck(this) and
exists(MethodAccess ma, Expr checked | isPathTraversalCheck(ma, checked) |
- DataFlow::localExprFlow(checked, e)
- or
- ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ // Either the path traversal check comes before the guard
+ DataFlow::localExprFlow(checked, e) or
+ // or both checks are in the same condition
+ // (for example, `path.startsWith(BASE_PATH) && !path.contains("..")`)
+ ma.(Guard).controls(this.getBasicBlock(), _) or
+ this.controls(ma.getBasicBlock(), branch)
) and
branch = true
or
+ // When using a blocklist, that is, checking for known bad patterns in the path,
+ // (for example, `path.startsWith("/WEB-INF/")` or `path.contains("..")`)
+ // the application needs to protect against double URL encoding bypasses.
isDisallowListCheck(this) and
exists(MethodAccess ma, Expr checked | isURLEncodingCheck(ma, checked) |
- DataFlow::localExprFlow(checked, e)
- or
- ma.getParent*().(BinaryExpr) = this.(MethodAccess).getParent*()
+ // Either the URL encoding check comes before the guard
+ DataFlow::localExprFlow(checked, e) or
+ // or both checks are in the same condition
+ // (for example, `!path.contains("..") && !path.contains("%")`)
+ ma.(Guard).controls(this.getBasicBlock(), _) or
+ this.controls(ma.getBasicBlock(), branch)
) and
branch = false
)
From fdf77ad2b99ff13205320e0a1ea624049c93c4f1 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Fri, 14 Jan 2022 15:07:29 +0000
Subject: [PATCH 031/296] Update version numbers for LGTM 1.29
---
docs/codeql/support/conf.py | 9 ++++++---
docs/codeql/support/framework-support.rst | 2 +-
docs/codeql/support/language-support.rst | 3 +--
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/docs/codeql/support/conf.py b/docs/codeql/support/conf.py
index 3d2f5d6cf81..b4000e35b95 100644
--- a/docs/codeql/support/conf.py
+++ b/docs/codeql/support/conf.py
@@ -41,9 +41,12 @@ project = u'Supported languages and frameworks for LGTM Enterprise'
# The version info for this project, if different from version and release in main conf.py file.
# The short X.Y version.
-version = u'1.27'
-# The full version, including alpha/beta/rc tags.
-release = u'1.27'
+
+# LGTM Enterprise release
+release = u'1.29'
+
+# CodeQL CLI version used by LGTM Enterprise release
+version = u'2.6.4'
# -- Project-specifc options for HTML output ----------------------------------------------
diff --git a/docs/codeql/support/framework-support.rst b/docs/codeql/support/framework-support.rst
index d04293adfe5..8f9664cf63e 100644
--- a/docs/codeql/support/framework-support.rst
+++ b/docs/codeql/support/framework-support.rst
@@ -1,7 +1,7 @@
Frameworks and libraries
########################
-The libraries and queries in version |version| have been explicitly checked against the libraries and frameworks listed below.
+LGTM Enterprise |release| includes CodeQL CLI |version|. The CodeQL libraries and queries used by this version of LGTM Enterprise have been explicitly checked against the libraries and frameworks listed below.
.. pull-quote::
diff --git a/docs/codeql/support/language-support.rst b/docs/codeql/support/language-support.rst
index b716b802427..034d5db23f0 100644
--- a/docs/codeql/support/language-support.rst
+++ b/docs/codeql/support/language-support.rst
@@ -1,8 +1,7 @@
Languages and compilers
#######################
-CodeQL and LGTM version |version| support analysis of the following languages compiled by the following compilers.
-(CodeQL was previously known as QL.)
+LGTM Enterprise |release| includes CodeQL CLI |version|. LGTM Enterprise supports analysis of the following languages compiled by the following compilers.
Note that where there are several versions or dialects of a language, the supported variants are listed.
If your code requires a particular version of a compiler, check that this version is included below.
From eb1806c0a92d23dbd87fcc9b62fb11d1c5370711 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Fri, 14 Jan 2022 17:12:02 +0100
Subject: [PATCH 032/296] Split PathMatchGuard into three guards
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 180 ++++++++++--------
1 file changed, 97 insertions(+), 83 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 119670cdd14..89b2ca39300 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -34,14 +34,6 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
/** A barrier guard that protects against URL forward vulnerabilities. */
abstract class UnsafeUrlForwardBarrierGuard extends DataFlow::BarrierGuard { }
-/**
- * Holds if `ma` is a call to a method that checks exact match of string.
- */
-private predicate isExactStringPathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().getName() = ["equals", "equalsIgnoreCase"]
-}
-
/**
* Holds if `ma` is a call to a method that checks a path string.
*/
@@ -59,44 +51,47 @@ private predicate isFilePathMatch(MethodAccess ma) {
ma.getMethod().getName() = "startsWith"
}
-/**
- * Holds if `ma` protects against path traversal, by either:
- * * looking for the literal `..`
- * * performing path normalization
- */
-private predicate isPathTraversalCheck(MethodAccess ma, Expr checked) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
- ma.(Guard).controls(checked.getBasicBlock(), false)
- or
- ma.getMethod() instanceof PathNormalizeMethod and
- checked = ma
+/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
+private class PathTraversalGuard extends Guard instanceof MethodAccess {
+ Expr checked;
+
+ PathTraversalGuard() {
+ this.getMethod().getDeclaringType() instanceof TypeString and
+ this.getMethod().hasName(["contains", "indexOf"]) and
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
+ this.controls(checked.getBasicBlock(), false)
+ }
+
+ predicate checks(Expr e) { checked = e }
}
-/**
- * Holds if `ma` protects against double URL encoding, by either:
- * * looking for the literal `%`
- * * performing URL decoding
- */
-private predicate isURLEncodingCheck(MethodAccess ma, Expr checked) {
- // Search the special character `%` used in url encoding
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().hasName(["contains", "indexOf"]) and
- ma.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
- ma.(Guard).controls(checked.getBasicBlock(), false)
- or
- // Call to `URLDecoder` assuming the implementation handles double encoding correctly
- ma.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
- ma.getMethod().hasName("decode") and
- checked = ma
+/** A complementary sanitizer that protects against path traversal using path normalization. */
+private class PathNormalizeSanitizer extends MethodAccess {
+ PathNormalizeSanitizer() {
+ this.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
+ this.getMethod().hasName("normalize")
+ }
}
-/** The Java method `normalize` of `java.nio.file.Path`. */
-private class PathNormalizeMethod extends Method {
- PathNormalizeMethod() {
- this.getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
- this.hasName("normalize")
+/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
+private class UrlEncodingGuard extends Guard instanceof MethodAccess {
+ Expr checked;
+
+ UrlEncodingGuard() {
+ this.getMethod().getDeclaringType() instanceof TypeString and
+ this.getMethod().hasName(["contains", "indexOf"]) and
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
+ this.controls(checked.getBasicBlock(), false)
+ }
+
+ predicate checks(Expr e) { checked = e }
+}
+
+/** A complementary sanitizer that protects against double URL encoding using URL decoding. */
+private class UrlDecodeSanitizer extends MethodAccess {
+ UrlDecodeSanitizer() {
+ this.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
+ this.getMethod().hasName("decode")
}
}
@@ -104,60 +99,79 @@ private predicate isDisallowedWord(CompileTimeConstantExpr word) {
word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
}
-private predicate isAllowListCheck(MethodAccess ma) {
- (isStringPathMatch(ma) or isFilePathMatch(ma)) and
- not isDisallowedWord(ma.getAnArgument())
-}
-
-private predicate isDisallowListCheck(MethodAccess ma) {
- (isStringPathMatch(ma) or isFilePathMatch(ma)) and
- isDisallowedWord(ma.getAnArgument())
-}
-
/**
- * A guard that checks a path with the following methods:
- * 1. Exact string match
- * 2. Path matches allowed values (needs to protect against path traversal)
- * 3. Path matches disallowed values (needs to protect against URL encoding)
+ * A guard that considers safe a string being exactly compared to a trusted value.
*/
-private class PathMatchGuard extends UnsafeUrlForwardBarrierGuard {
- PathMatchGuard() {
- isExactStringPathMatch(this) or isAllowListCheck(this) or isDisallowListCheck(this)
+private class ExactStringPathMatchGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
+ ExactStringPathMatchGuard() {
+ this.getMethod().getDeclaringType() instanceof TypeString and
+ this.getMethod().getName() = ["equals", "equalsIgnoreCase"]
}
override predicate checks(Expr e, boolean branch) {
e = this.(MethodAccess).getQualifier() and
+ branch = true
+ }
+}
+
+/**
+ * A guard that considers safe a string being matched against an allowlist of partial trusted values.
+ * This requires additional protection against path traversal, either another guard (`PathTraversalGuard`)
+ * or a sanitizer (`PathNormalizeSanitizer`).
+ */
+private class AllowListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
+ AllowListCheckGuard() {
+ (isStringPathMatch(this) or isFilePathMatch(this)) and
+ not isDisallowedWord(this.getAnArgument())
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and
+ branch = true and
(
- isExactStringPathMatch(this) and
- branch = true
+ // Either the path normalization sanitizer comes before the guard
+ exists(PathNormalizeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
- // When using an allowlist, that is, checking for known safe paths
- // (for example, `path.startsWith(BASE_PATH)`)
- // the application needs to protect against path traversal bypasses.
- isAllowListCheck(this) and
- exists(MethodAccess ma, Expr checked | isPathTraversalCheck(ma, checked) |
- // Either the path traversal check comes before the guard
- DataFlow::localExprFlow(checked, e) or
+ // or the path traversal check comes before the guard
+ exists(PathTraversalGuard guard |
+ guard.checks(any(Expr checked | DataFlow::localExprFlow(checked, e))) or
// or both checks are in the same condition
// (for example, `path.startsWith(BASE_PATH) && !path.contains("..")`)
- ma.(Guard).controls(this.getBasicBlock(), _) or
- this.controls(ma.getBasicBlock(), branch)
- ) and
- branch = true
+ guard.controls(this.getBasicBlock().(ConditionBlock), false) or
+ this.controls(guard.getBasicBlock().(ConditionBlock), branch)
+ )
+ )
+ }
+}
+
+/**
+ * A guard that considers safe a string being matched against a blocklist of known dangerous values.
+ * This requires additional protection against path traversal, either another guard (`UrlEncodingGuard`)
+ * or a sanitizer (`UrlDecodeSanitizer`).
+ */
+private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
+ BlockListCheckGuard() {
+ (isStringPathMatch(this) or isFilePathMatch(this)) and
+ isDisallowedWord(this.getAnArgument())
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.(MethodAccess).getQualifier() and
+ branch = false and
+ (
+ // Either the URL decode sanitization comes before the guard
+ exists(UrlDecodeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
- // When using a blocklist, that is, checking for known bad patterns in the path,
- // (for example, `path.startsWith("/WEB-INF/")` or `path.contains("..")`)
- // the application needs to protect against double URL encoding bypasses.
- isDisallowListCheck(this) and
- exists(MethodAccess ma, Expr checked | isURLEncodingCheck(ma, checked) |
- // Either the URL encoding check comes before the guard
- DataFlow::localExprFlow(checked, e) or
+ // or the URL encoding check comes before the guard
+ exists(UrlEncodingGuard guard |
+ guard.checks(any(Expr checked | DataFlow::localExprFlow(checked, e)))
+ or
// or both checks are in the same condition
// (for example, `!path.contains("..") && !path.contains("%")`)
- ma.(Guard).controls(this.getBasicBlock(), _) or
- this.controls(ma.getBasicBlock(), branch)
- ) and
- branch = false
+ guard.controls(this.getBasicBlock().(ConditionBlock), false)
+ or
+ this.controls(guard.getBasicBlock().(ConditionBlock), branch)
+ )
)
}
}
From a2c98baf29941f171128f21e189b18b7604b8b68 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Fri, 14 Jan 2022 17:14:28 +0100
Subject: [PATCH 033/296] Reordering
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 173 +++++++++---------
1 file changed, 87 insertions(+), 86 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 89b2ca39300..924757ddf13 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -7,9 +7,37 @@ import semmle.code.java.frameworks.spring.SpringWeb
import semmle.code.java.security.RequestForgery
private import semmle.code.java.dataflow.StringPrefixes
-/** A sanitizer for unsafe url forward vulnerabilities. */
+/** A sink for unsafe URL forward vulnerabilities. */
+abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
+
+/** A sanitizer for unsafe URL forward vulnerabilities. */
abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { }
+/** A barrier guard that protects against URL forward vulnerabilities. */
+abstract class UnsafeUrlForwardBarrierGuard extends DataFlow::BarrierGuard { }
+
+/** An argument to `getRequestDispatcher`. */
+private class RequestDispatcherSink extends UnsafeUrlForwardSink {
+ RequestDispatcherSink() {
+ exists(MethodAccess ma |
+ ma.getMethod() instanceof GetRequestDispatcherMethod and
+ ma.getArgument(0) = this.asExpr()
+ )
+ }
+}
+
+/** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
+private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
+ SpringModelAndViewSink() {
+ exists(ClassInstanceExpr cie |
+ cie.getConstructedType() instanceof ModelAndView and
+ cie.getArgument(0) = this.asExpr()
+ )
+ or
+ exists(SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc.getArgument(0) = this.asExpr())
+ }
+}
+
private class PrimitiveSanitizer extends UnsafeUrlForwardSanitizer {
PrimitiveSanitizer() {
this.getType() instanceof PrimitiveType or
@@ -31,74 +59,6 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
FollowsSanitizingPrefix() { this.asExpr() = any(SanitizingPrefix fp).getAnAppendedExpression() }
}
-/** A barrier guard that protects against URL forward vulnerabilities. */
-abstract class UnsafeUrlForwardBarrierGuard extends DataFlow::BarrierGuard { }
-
-/**
- * Holds if `ma` is a call to a method that checks a path string.
- */
-private predicate isStringPathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypeString and
- ma.getMethod().getName() =
- ["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
-}
-
-/**
- * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
- */
-private predicate isFilePathMatch(MethodAccess ma) {
- ma.getMethod().getDeclaringType() instanceof TypePath and
- ma.getMethod().getName() = "startsWith"
-}
-
-/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
-private class PathTraversalGuard extends Guard instanceof MethodAccess {
- Expr checked;
-
- PathTraversalGuard() {
- this.getMethod().getDeclaringType() instanceof TypeString and
- this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
- this.controls(checked.getBasicBlock(), false)
- }
-
- predicate checks(Expr e) { checked = e }
-}
-
-/** A complementary sanitizer that protects against path traversal using path normalization. */
-private class PathNormalizeSanitizer extends MethodAccess {
- PathNormalizeSanitizer() {
- this.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
- this.getMethod().hasName("normalize")
- }
-}
-
-/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
-private class UrlEncodingGuard extends Guard instanceof MethodAccess {
- Expr checked;
-
- UrlEncodingGuard() {
- this.getMethod().getDeclaringType() instanceof TypeString and
- this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
- this.controls(checked.getBasicBlock(), false)
- }
-
- predicate checks(Expr e) { checked = e }
-}
-
-/** A complementary sanitizer that protects against double URL encoding using URL decoding. */
-private class UrlDecodeSanitizer extends MethodAccess {
- UrlDecodeSanitizer() {
- this.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
- this.getMethod().hasName("decode")
- }
-}
-
-private predicate isDisallowedWord(CompileTimeConstantExpr word) {
- word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
-}
-
/**
* A guard that considers safe a string being exactly compared to a trusted value.
*/
@@ -176,27 +136,68 @@ private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceo
}
}
-abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
+/**
+ * Holds if `ma` is a call to a method that checks a path string.
+ */
+private predicate isStringPathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypeString and
+ ma.getMethod().getName() =
+ ["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
+}
-/** An argument to `getRequestDispatcher`. */
-private class RequestDispatcherSink extends UnsafeUrlForwardSink {
- RequestDispatcherSink() {
- exists(MethodAccess ma |
- ma.getMethod() instanceof GetRequestDispatcherMethod and
- ma.getArgument(0) = this.asExpr()
- )
+/**
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
+ */
+private predicate isFilePathMatch(MethodAccess ma) {
+ ma.getMethod().getDeclaringType() instanceof TypePath and
+ ma.getMethod().getName() = "startsWith"
+}
+
+private predicate isDisallowedWord(CompileTimeConstantExpr word) {
+ word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
+}
+
+/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
+private class PathTraversalGuard extends Guard instanceof MethodAccess {
+ Expr checked;
+
+ PathTraversalGuard() {
+ this.getMethod().getDeclaringType() instanceof TypeString and
+ this.getMethod().hasName(["contains", "indexOf"]) and
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
+ this.controls(checked.getBasicBlock(), false)
+ }
+
+ predicate checks(Expr e) { checked = e }
+}
+
+/** A complementary sanitizer that protects against path traversal using path normalization. */
+private class PathNormalizeSanitizer extends MethodAccess {
+ PathNormalizeSanitizer() {
+ this.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
+ this.getMethod().hasName("normalize")
}
}
-/** An argument to `new ModelAndView` or `ModelAndView.setViewName`. */
-private class SpringModelAndViewSink extends UnsafeUrlForwardSink {
- SpringModelAndViewSink() {
- exists(ClassInstanceExpr cie |
- cie.getConstructedType() instanceof ModelAndView and
- cie.getArgument(0) = this.asExpr()
- )
- or
- exists(SpringModelAndViewSetViewNameCall smavsvnc | smavsvnc.getArgument(0) = this.asExpr())
+/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
+private class UrlEncodingGuard extends Guard instanceof MethodAccess {
+ Expr checked;
+
+ UrlEncodingGuard() {
+ this.getMethod().getDeclaringType() instanceof TypeString and
+ this.getMethod().hasName(["contains", "indexOf"]) and
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
+ this.controls(checked.getBasicBlock(), false)
+ }
+
+ predicate checks(Expr e) { checked = e }
+}
+
+/** A complementary sanitizer that protects against double URL encoding using URL decoding. */
+private class UrlDecodeSanitizer extends MethodAccess {
+ UrlDecodeSanitizer() {
+ this.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
+ this.getMethod().hasName("decode")
}
}
From 978ef1570a7fcbefdedb5a75a5a484e33f45b323 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Sun, 16 Jan 2022 01:11:25 +0000
Subject: [PATCH 034/296] Update method names
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 924757ddf13..c245b7ffb0a 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -81,7 +81,7 @@ private class ExactStringPathMatchGuard extends UnsafeUrlForwardBarrierGuard ins
*/
private class AllowListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
AllowListCheckGuard() {
- (isStringPathMatch(this) or isFilePathMatch(this)) and
+ (isStringPartialMatch(this) or isPathPartialMatch(this)) and
not isDisallowedWord(this.getAnArgument())
}
@@ -111,7 +111,7 @@ private class AllowListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceo
*/
private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
BlockListCheckGuard() {
- (isStringPathMatch(this) or isFilePathMatch(this)) and
+ (isStringPartialMatch(this) or isPathPartialMatch(this)) and
isDisallowedWord(this.getAnArgument())
}
@@ -137,18 +137,18 @@ private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceo
}
/**
- * Holds if `ma` is a call to a method that checks a path string.
+ * Holds if `ma` is a call to a method that checks a partial string match.
*/
-private predicate isStringPathMatch(MethodAccess ma) {
+private predicate isStringPartialMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod().getName() =
["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
}
/**
- * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a path.
+ * Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a partial path match.
*/
-private predicate isFilePathMatch(MethodAccess ma) {
+private predicate isPathPartialMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypePath and
ma.getMethod().getName() = "startsWith"
}
From 4797fce48a3d78adc95223a25a027f5e992cf078 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Sun, 16 Jan 2022 01:15:29 +0000
Subject: [PATCH 035/296] Update use cases and qldoc
---
.../CWE-552/UnsafeServletRequestDispatch.java | 91 +++++++------------
.../CWE/CWE-552/UnsafeUrlForward.qhelp | 3 +
2 files changed, 35 insertions(+), 59 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
index 042a188c4c7..59458912f24 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
@@ -5,78 +5,51 @@ public class UnsafeServletRequestDispatch extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
{
- // GOOD: whitelisted URI
+ ServletConfig cfg = getServletConfig();
+ ServletContext sc = cfg.getServletContext();
+
+ // GOOD: check for an explicitly permitted URI
+ String action = request.getParameter("action");
if (action.equals("Login")) {
- ServletContext sc = cfg.getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher("/Login.jsp");
rd.forward(request, response);
- }
- }
+ }
- {
- // BAD: Request dispatcher constructed from `ServletContext` without input validation
+ // BAD: no URI validation
String returnURL = request.getParameter("returnURL");
- ServletConfig cfg = getServletConfig();
-
- ServletContext sc = cfg.getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
rd.forward(request, response);
- }
- {
- // BAD: Request dispatcher without path traversal check
+ // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
+ // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
String path = request.getParameter("path");
- // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
- // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
+ // BAD: no check for path traversal
if (path.startsWith(BASE_PATH)) {
request.getServletContext().getRequestDispatcher(path).include(request, response);
}
+
+ // GOOD: To check there won't be unexpected path traversal, we can check for any `..` sequences and whether the URI starts with a given web root path.
+ if (path.startsWith(BASE_PATH) && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
+
+ // GOOD: Or alternatively we can use Path.normalize and check whether the URI starts with a given web root path.
+ Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
+ if (requestedPath.startsWith(BASE_PATH)) {
+ request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
+ }
+
+ // GOOD: Or alternatively ensure URL encoding is removed and then check for any `..` sequences.
+ boolean hasEncoding = path.contains("%");
+ while (hasEncoding) {
+ path = URLDecoder.decode(path, "UTF-8");
+ hasEncoding = path.contains("%");
+ }
+
+ if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
+ request.getServletContext().getRequestDispatcher(path).include(request, response);
+ }
}
}
-
- {
- // GOOD: Request dispatcher with path traversal check
- String path = request.getParameter("path");
-
- if (path.startsWith(BASE_PATH) && !path.contains("..")) {
- request.getServletContext().getRequestDispatcher(path).include(request, response);
- }
- }
-
- {
- // GOOD: Request dispatcher with path normalization
- String path = request.getParameter("path");
- Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
-
- // /pages/welcome.jsp/../../WEB-INF/web.xml becomes /WEB-INF/web.xml
- // /pages/welcome.jsp/../../%57EB-INF/web.xml becomes /%57EB-INF/web.xml
- if (requestedPath.startsWith(BASE_PATH)) {
- request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
- }
- }
-
- {
- // BAD: Request dispatcher with improper negation check and without url decoding
- String path = request.getParameter("path");
- Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
-
- if (!requestedPath.startsWith("/WEB-INF") && !requestedPath.startsWith("/META-INF")) {
- request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
- }
- }
-
- {
- // GOOD: Request dispatcher with path traversal check and url decoding
- String path = request.getParameter("path");
- boolean hasEncoding = path.contains("%");
- while (hasEncoding) {
- path = URLDecoder.decode(path, "UTF-8");
- hasEncoding = path.contains("%");
- }
-
- if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
- request.getServletContext().getRequestDispatcher(path).include(request, response);
- }
- }
}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
index b8a3ddda77f..5b1022d50ee 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
@@ -13,6 +13,9 @@
Unsanitized user provided data must not be used to construct the path for URL forwarding. In order to prevent
untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.
+Instead, user input should be checked for path traversal using .. sequences or the user input should
+be normalized using Path.normalize, any URL encoding should be removed, and user input should be
+checked against a permitted URI.
From d09f48ecb418d84218d01780119ac0b7d1449ab0 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Sun, 16 Jan 2022 20:56:13 +0000
Subject: [PATCH 036/296] Ruby: flag up protect_from_forgery calls without an
exception strategy
---
.../ruby/frameworks/ActionController.qll | 20 +++++++++++++++++++
.../cwe-352/CSRFProtectionDisabled.qhelp | 11 ++++++++++
.../cwe-352/CSRFProtectionDisabled.ql | 8 ++++----
3 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
index a47c7644272..ec4a44418cc 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
@@ -297,3 +297,23 @@ class ActionControllerSkipForgeryProtectionCall extends CSRFProtectionSetting::R
override boolean getVerificationSetting() { result = false }
}
+
+/**
+ * A call to `protect_from_forgery`.
+ */
+private class ActionControllerProtectFromForgeryCall extends CSRFProtectionSetting::Range {
+ private ActionControllerContextCall callExpr;
+
+ ActionControllerProtectFromForgeryCall() {
+ callExpr = this.asExpr().getExpr() and
+ callExpr.getMethodName() = "protect_from_forgery"
+ }
+
+ private string getWithValueText() { result = callExpr.getKeywordArgument("with").getValueText() }
+
+ // Calls without `with: :exception` can allow for bypassing CSRF protection
+ // in some scenarios.
+ override boolean getVerificationSetting() {
+ if this.getWithValueText() = "exception" then result = true else result = false
+ }
+}
diff --git a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
index b496ce0eca5..8b5ff38d5a3 100644
--- a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
+++ b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
@@ -50,12 +50,23 @@
skip_before_action.
+
+ Care should be taken when using the Rails
+ protect_from_forgery method to prevent CSRF. The default
+ behaviour of this method is to null the session when an invalid CSRF token
+ is provided. This may not be sufficient to avoid a CSRF vulnerability -
+ for example if parts of the session are memoized. Calling
+ protect_from_forgery with: :exception can help to avoid this
+ by raising an exception on an invalid CSRF token instead.
+
+
Wikipedia: Cross-site request forgery
OWASP: Cross-site request forgery
Securing Rails Applications: Cross-Site Request Forgery (CSRF)
+ Veracode: When Rails' protect_from_forgery Fails .
diff --git a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
index 6b997450f53..65028241fe1 100644
--- a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
+++ b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
@@ -1,7 +1,7 @@
/**
- * @name CSRF protection disabled
- * @description Disabling CSRF protection makes the application vulnerable to
- * a Cross-Site Request Forgery (CSRF) attack.
+ * @name CSRF protection weakened or disabled
+ * @description Disabling or weakening CSRF protection may make the application
+ * vulnerable to a Cross-Site Request Forgery (CSRF) attack.
* @kind problem
* @problem.severity warning
* @security-severity 8.8
@@ -16,4 +16,4 @@ import codeql.ruby.Concepts
from CSRFProtectionSetting s
where s.getVerificationSetting() = false
-select s, "Potential CSRF vulnerability due to forgery protection being disabled."
+select s, "Potential CSRF vulnerability due to forgery protection being disabled or weakened."
From 16aa53a928580163dca89b15ff5371bf7f80e1bc Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Mon, 17 Jan 2022 10:35:34 +0000
Subject: [PATCH 037/296] Add security tag to java/random-used-once
Raised in https://github.com/github/codeql/issues/7601, this is one of the only .ql files that has a security-severity score but not the tag "security", including many other queries that live outside the `Security/` subdirectory.
Besides this the only other files with this security-severity-but-no-security-tag combination are:
```
java/ql/src/Frameworks/JavaEE/EJB/EjbContainerInterference.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbFileIO.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbNative.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbReflection.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSecurityConfiguration.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSerialization.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSetSocketOrUrlFactory.ql
```
Given their location I'm assuming these queries are disabled by default and likely shouldn't changed?
---
java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
index f502d07440f..6bf44839dd4 100644
--- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
+++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
@@ -9,6 +9,7 @@
* @id java/random-used-once
* @tags reliability
* maintainability
+ * security
* external/cwe/cwe-335
*/
From c17bd2964093f1d7b31a4bb6177478057b79d660 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:39:54 +0100
Subject: [PATCH 038/296] C#: Rename C# code file and update test.
---
.../csharp10/{RecordTypeSealedToString.cs => RecordTypes.cs} | 0
.../library-tests/csharp10/recordTypeSealedToString.expected | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
rename csharp/ql/test/library-tests/csharp10/{RecordTypeSealedToString.cs => RecordTypes.cs} (100%)
diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
similarity index 100%
rename from csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs
rename to csharp/ql/test/library-tests/csharp10/RecordTypes.cs
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
index c8f326c449c..1da3b58b9e3 100644
--- a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
+++ b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
@@ -1 +1 @@
-| RecordTypeSealedToString.cs:5:35:5:42 | ToString |
+| RecordTypes.cs:5:35:5:42 | ToString |
From dc76775d07041e5bdac73a326a40852536b1c07d Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:43:33 +0100
Subject: [PATCH 039/296] C#: Consider 'record' a type modifier in the
extractor (it can be applied to both class and struct).
---
csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
index 3d6cb01837e..a94f0b54747 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
@@ -111,6 +111,9 @@ namespace Semmle.Extraction.CSharp.Entities
if (nt is null)
throw new InternalError(symbol, "Symbol kind is inconsistent with its type");
+ if (nt.IsRecord)
+ HasModifier(cx, trapFile, key, "record");
+
if (nt.TypeKind == TypeKind.Struct)
{
if (nt.IsReadOnly)
From 55cb2aa1604dfe895a01ef9b90bee54d8d492f1e Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:45:27 +0100
Subject: [PATCH 040/296] C#: Use modifier to decide, if a type is a record
like type and implement support for record struct types.
---
csharp/ql/lib/semmle/code/cil/Types.qll | 2 +-
csharp/ql/lib/semmle/code/csharp/Type.qll | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/csharp/ql/lib/semmle/code/cil/Types.qll b/csharp/ql/lib/semmle/code/cil/Types.qll
index 1dfaa0191a1..6bb980d6a87 100644
--- a/csharp/ql/lib/semmle/code/cil/Types.qll
+++ b/csharp/ql/lib/semmle/code/cil/Types.qll
@@ -61,7 +61,7 @@ class Class extends ValueOrRefType {
}
/** A `record`. */
-class Record extends Class {
+deprecated class Record extends Class {
Record() { this.isRecord() }
}
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index 5aeaeb904d5..ac7e3390a5d 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -372,6 +372,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
nested_types(this, _, result)
}
+ override predicate isRecord() { this.hasModifier("record") }
+
override string toString() { result = Type.super.toString() }
}
@@ -711,6 +713,20 @@ class Struct extends ValueType, @struct_type {
override string getAPrimaryQlClass() { result = "Struct" }
}
+/**
+ * A `record struct`, for example
+ * ```csharp
+ * record struct RS {
+ * ...
+ * }
+ * ```
+ */
+class RecordStruct extends Struct {
+ RecordStruct() { this.isRecord() }
+
+ override string getAPrimaryQlClass() { result = "RecordStruct" }
+}
+
/**
* A reference type.
*
From 9770f098397bc2aec0f3c7fed70fa851663884d4 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:00:39 +0100
Subject: [PATCH 041/296] C#: Deprecate Record and introduce RecordClass
instead. Also make flow summary support for record struct constructors.
---
csharp/ql/lib/semmle/code/csharp/Type.qll | 28 +++++++++++++++----
.../code/csharp/dataflow/FlowSummary.qll | 2 +-
.../ql/lib/semmle/code/csharp/exprs/Expr.qll | 4 ++-
.../library-tests/csharp9/PrintAst.expected | 20 ++++++-------
.../ql/test/library-tests/csharp9/record.ql | 4 +--
.../dataflow/tuples/PrintAst.expected | 2 +-
6 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index ac7e3390a5d..57db0fa11a7 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -451,6 +451,14 @@ class SimpleType extends ValueType, @simple_type {
override SystemNamespace getDeclaringNamespace() { any() }
}
+/**
+ * A `record` like type.
+ * This can be either a `class` or a `struct`.
+ */
+abstract class RecordType extends ValueOrRefType {
+ RecordType() { this.isRecord() }
+}
+
/**
* The Boolean type, `bool`.
*/
@@ -721,7 +729,7 @@ class Struct extends ValueType, @struct_type {
* }
* ```
*/
-class RecordStruct extends Struct {
+class RecordStruct extends RecordType, Struct {
RecordStruct() { this.isRecord() }
override string getAPrimaryQlClass() { result = "RecordStruct" }
@@ -781,6 +789,18 @@ class Class extends RefType, @class_type {
override string getAPrimaryQlClass() { result = "Class" }
}
+/**
+ * DEPRECATED: Use `RecordClass` instead.
+ */
+deprecated class Record extends Class {
+ Record() { this.isRecord() }
+
+ /** Gets the clone method of this record. */
+ RecordCloneMethod getCloneMethod() { result = this.getAMember() }
+
+ override string getAPrimaryQlClass() { result = "Record" }
+}
+
/**
* A `record`, for example
*
@@ -790,13 +810,11 @@ class Class extends RefType, @class_type {
* }
* ```
*/
-class Record extends Class {
- Record() { this.isRecord() }
-
+class RecordClass extends RecordType, Class {
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
- override string getAPrimaryQlClass() { result = "Record" }
+ override string getAPrimaryQlClass() { result = "RecordClass" }
}
/**
diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
index 94b3d8d7d4d..270991757f6 100644
--- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
+++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
@@ -111,7 +111,7 @@ module SummaryComponentStack {
class SummarizedCallable = Impl::Public::SummarizedCallable;
private predicate recordConstructorFlow(Constructor c, int i, Property p) {
- c = any(Record r).getAMember() and
+ c = any(RecordType r).getAMember() and
exists(string name |
c.getParameter(i).getName() = name and
c.getDeclaringType().getAMember(name) = p
diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
index 1007d2cefe6..1a869f2458c 100644
--- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
+++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
@@ -1175,7 +1175,9 @@ class WithExpr extends Expr, @with_expr {
Expr getExpr() { result = this.getChild(0) }
/** Gets the clone method of the `record` that is targetted by this `with` expression. */
- RecordCloneMethod getCloneMethod() { result = this.getExpr().getType().(Record).getCloneMethod() }
+ RecordCloneMethod getCloneMethod() {
+ result = this.getExpr().getType().(RecordClass).getCloneMethod()
+ }
override string toString() { result = "... with { ... }" }
diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
index cb6414d9bb4..5c76d399ed2 100644
--- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
@@ -776,7 +776,7 @@ ParenthesizedPattern.cs:
# 26| 0: [TypeMention] string
# 26| 2: [IntLiteral] 5
Record.cs:
-# 4| [Record] Person
+# 4| [Record,RecordClass] Person
# 4| 11: [NEOperator] !=
#-----| 2: (Parameters)
# 4| 0: [Parameter] left
@@ -806,7 +806,7 @@ Record.cs:
# 9| 1: [TupleExpr] (..., ...)
# 9| 0: [ParameterAccess] access to parameter first
# 9| 1: [ParameterAccess] access to parameter last
-# 12| [Record] Teacher
+# 12| [Record,RecordClass] Teacher
# 12| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 12| 0: [Parameter] left
@@ -834,7 +834,7 @@ Record.cs:
# 17| 4: [AssignExpr] ... = ...
# 17| 0: [PropertyCall] access to property Subject
# 17| 1: [ParameterAccess] access to parameter sub
-# 20| [Record] Student
+# 20| [Record,RecordClass] Student
# 20| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 20| 0: [Parameter] left
@@ -862,7 +862,7 @@ Record.cs:
# 24| 4: [AssignExpr] ... = ...
# 24| 0: [PropertyCall] access to property Level
# 24| 1: [ParameterAccess] access to parameter level
-# 27| [Record] Person1
+# 27| [Record,RecordClass] Person1
# 27| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 27| 0: [Parameter] left
@@ -889,7 +889,7 @@ Record.cs:
# 27| 4: [Setter] set_LastName
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
-# 29| [Record] Teacher1
+# 29| [Record,RecordClass] Teacher1
# 29| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 29| 0: [Parameter] left
@@ -913,7 +913,7 @@ Record.cs:
# 29| 4: [Setter] set_Subject
#-----| 2: (Parameters)
# 29| 0: [Parameter] value
-# 32| [Record] Student1
+# 32| [Record,RecordClass] Student1
# 32| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 32| 0: [Parameter] left
@@ -937,7 +937,7 @@ Record.cs:
# 32| 4: [Setter] set_Level
#-----| 2: (Parameters)
# 32| 0: [Parameter] value
-# 35| [Record] Pet
+# 35| [Record,RecordClass] Pet
# 35| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 35| 0: [Parameter] left
@@ -963,7 +963,7 @@ Record.cs:
# 38| -1: [TypeAccess] access to type Console
# 38| 0: [TypeMention] Console
# 38| 0: [StringLiteral] "Shredding furniture"
-# 41| [Record] Dog
+# 41| [Record,RecordClass] Dog
# 41| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 41| 0: [Parameter] left
@@ -1002,7 +1002,7 @@ Record.cs:
# 50| 0: [MethodCall] call to method ToString
# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteral] " is a dog"
-# 54| [Record] R1
+# 54| [Record,RecordClass] R1
# 54| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 54| 0: [Parameter] left
@@ -1022,7 +1022,7 @@ Record.cs:
# 54| 4: [Setter] set_A
#-----| 2: (Parameters)
# 54| 0: [Parameter] value
-# 56| [Record] R2
+# 56| [Record,RecordClass] R2
# 56| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 56| 0: [Parameter] left
diff --git a/csharp/ql/test/library-tests/csharp9/record.ql b/csharp/ql/test/library-tests/csharp9/record.ql
index 9a8da357d69..7fc45550365 100644
--- a/csharp/ql/test/library-tests/csharp9/record.ql
+++ b/csharp/ql/test/library-tests/csharp9/record.ql
@@ -1,6 +1,6 @@
import csharp
-query predicate records(Record t, string i, RecordCloneMethod clone) {
+query predicate records(RecordClass t, string i, RecordCloneMethod clone) {
t.getABaseInterface().toStringWithTypes() = i and
clone = t.getCloneMethod() and
t.fromSource()
@@ -10,7 +10,7 @@ private string getMemberName(Member m) {
result = m.getDeclaringType().getQualifiedName() + "." + m.toStringWithTypes()
}
-query predicate members(Record t, string ms, string l) {
+query predicate members(RecordClass t, string ms, string l) {
t.fromSource() and
exists(Member m | t.hasMember(m) |
ms = getMemberName(m) and
diff --git a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
index bfec8378220..6b509daa1bb 100644
--- a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
+++ b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
@@ -281,7 +281,7 @@ Tuples.cs:
# 81| 2: [ExprStmt] ...;
# 81| 0: [MethodCall] call to method Sink
# 81| 0: [LocalVariableAccess] access to local variable q
-# 85| 9: [Record] R1
+# 85| 9: [RecordClass] R1
# 85| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 85| 0: [Parameter] left
From 746fd603d8fd53f6be539a117b046d55e5cb690b Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:01:45 +0100
Subject: [PATCH 042/296] C#: Add flow summary test for record struct
constructors.
---
.../dataflow/fields/FieldFlow.expected | 123 ++++++++++--------
.../test/library-tests/dataflow/fields/J.cs | 14 +-
2 files changed, 83 insertions(+), 54 deletions(-)
diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
index 14e2c3d27b7..3ca4859dbed 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
+++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
@@ -776,28 +776,36 @@ edges
| I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
-| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object |
-| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
+| J.cs:14:17:14:33 | call to method Source : Object | J.cs:15:34:15:34 | access to local variable o : Object |
+| J.cs:14:17:14:33 | call to method Source : Object | J.cs:15:34:15:34 | access to local variable o : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
+| J.cs:34:17:34:33 | call to method Source : Object | J.cs:35:35:35:35 | access to local variable o : Object |
+| J.cs:34:17:34:33 | call to method Source : Object | J.cs:35:35:35:35 | access to local variable o : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
nodes
| A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C |
| A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C |
@@ -1637,32 +1645,42 @@ nodes
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
-| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
-| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
-| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
-| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
-| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
-| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:14:17:14:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:14:17:14:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
+| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
+| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
+| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:34:17:34:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:34:17:34:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
subpaths
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
@@ -1815,7 +1833,8 @@ subpaths
| I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object |
| I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object |
| I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:29 | call to method Source : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:29 | call to method Source : Object | call to method Source : Object |
-| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:23:14:23:21 | access to property Prop2 | J.cs:21:36:21:52 | call to method Source : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:21:36:21:52 | call to method Source : Object | call to method Source : Object |
+| J.cs:16:14:16:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:16:14:16:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:20:14:20:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:20:14:20:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:24:14:24:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:24:14:24:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:25:14:25:21 | access to property Prop2 | J.cs:23:36:23:52 | call to method Source : Object | J.cs:25:14:25:21 | access to property Prop2 | $@ | J.cs:23:36:23:52 | call to method Source : Object | call to method Source : Object |
+| J.cs:36:14:36:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:36:14:36:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object |
diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs
index b53cdb2e97e..8ac0404cd99 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/J.cs
+++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs
@@ -3,14 +3,16 @@ namespace System.Runtime.CompilerServices
internal static class IsExternalInit { }
}
-public record Record(object Prop1, object Prop2) { }
+public record class RecordClass(object Prop1, object Prop2) { }
+
+public record struct RecordStruct(object Prop1, object Prop2) { }
public class J
{
private void M1()
{
var o = Source(1);
- var r1 = new Record(o, null);
+ var r1 = new RecordClass(o, null);
Sink(r1.Prop1); // $ hasValueFlow=1
Sink(r1.Prop2); // no flow
@@ -27,6 +29,14 @@ public class J
Sink(r4.Prop2); // no flow
}
+ private void M2()
+ {
+ var o = Source(1);
+ var r1 = new RecordStruct(o, null);
+ Sink(r1.Prop1); // $ hasValueFlow=1
+ Sink(r1.Prop2); // no flow
+ }
+
public static void Sink(object o) { }
static T Source(object source) => throw null;
From 6c1bb4a3a9c9a9447f8804f2b4f1058f528e5cc7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:49:44 +0100
Subject: [PATCH 043/296] C#: Add test case for record class and record
structs.
---
csharp/ql/test/library-tests/csharp10/RecordTypes.cs | 8 +++++++-
.../test/library-tests/csharp10/recordTypes.expected | 11 +++++++++++
csharp/ql/test/library-tests/csharp10/recordTypes.ql | 7 +++++++
3 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 csharp/ql/test/library-tests/csharp10/recordTypes.expected
create mode 100644 csharp/ql/test/library-tests/csharp10/recordTypes.ql
diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
index 14dc3d77138..92ad18085f0 100644
--- a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
+++ b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
@@ -3,4 +3,10 @@ using System;
public record MyEntry(string Name, string Address)
{
sealed public override string ToString() => $"{Name} lives at {Address}";
-};
\ No newline at end of file
+};
+
+public record class MyClassRecord(DateTime stuff) { }
+
+public readonly record struct MyReadonlyRecordStruct(string Stuff) { }
+
+public record struct MyRecordStruct(int Stuff) { }
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.expected b/csharp/ql/test/library-tests/csharp10/recordTypes.expected
new file mode 100644
index 00000000000..75cef2ac7e7
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/recordTypes.expected
@@ -0,0 +1,11 @@
+recordTypes
+| RecordTypes.cs:3:1:6:2 | MyEntry |
+| RecordTypes.cs:8:1:8:53 | MyClassRecord |
+| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
+| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
+recordStructs
+| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
+| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
+recordClass
+| RecordTypes.cs:3:1:6:2 | MyEntry |
+| RecordTypes.cs:8:1:8:53 | MyClassRecord |
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.ql b/csharp/ql/test/library-tests/csharp10/recordTypes.ql
new file mode 100644
index 00000000000..1f96dab12da
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/recordTypes.ql
@@ -0,0 +1,7 @@
+import csharp
+
+query predicate recordTypes(RecordType rt) { any() }
+
+query predicate recordStructs(RecordStruct rs) { any() }
+
+query predicate recordClass(RecordClass r) { any() }
From b927aad6ed214e28148cf4984db6217571b5d6f0 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:43:21 +0100
Subject: [PATCH 044/296] C#: Address review comments related to record
structs.
---
csharp/ql/lib/semmle/code/csharp/Type.qll | 6 +-----
.../library-tests/csharp9/PrintAst.expected | 20 +++++++++----------
.../test/library-tests/dataflow/fields/J.cs | 4 ++--
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index 57db0fa11a7..c7f1515990b 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -455,7 +455,7 @@ class SimpleType extends ValueType, @simple_type {
* A `record` like type.
* This can be either a `class` or a `struct`.
*/
-abstract class RecordType extends ValueOrRefType {
+class RecordType extends ValueOrRefType {
RecordType() { this.isRecord() }
}
@@ -730,8 +730,6 @@ class Struct extends ValueType, @struct_type {
* ```
*/
class RecordStruct extends RecordType, Struct {
- RecordStruct() { this.isRecord() }
-
override string getAPrimaryQlClass() { result = "RecordStruct" }
}
@@ -797,8 +795,6 @@ deprecated class Record extends Class {
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
-
- override string getAPrimaryQlClass() { result = "Record" }
}
/**
diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
index 5c76d399ed2..e346a782c4f 100644
--- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
@@ -776,7 +776,7 @@ ParenthesizedPattern.cs:
# 26| 0: [TypeMention] string
# 26| 2: [IntLiteral] 5
Record.cs:
-# 4| [Record,RecordClass] Person
+# 4| [RecordClass] Person
# 4| 11: [NEOperator] !=
#-----| 2: (Parameters)
# 4| 0: [Parameter] left
@@ -806,7 +806,7 @@ Record.cs:
# 9| 1: [TupleExpr] (..., ...)
# 9| 0: [ParameterAccess] access to parameter first
# 9| 1: [ParameterAccess] access to parameter last
-# 12| [Record,RecordClass] Teacher
+# 12| [RecordClass] Teacher
# 12| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 12| 0: [Parameter] left
@@ -834,7 +834,7 @@ Record.cs:
# 17| 4: [AssignExpr] ... = ...
# 17| 0: [PropertyCall] access to property Subject
# 17| 1: [ParameterAccess] access to parameter sub
-# 20| [Record,RecordClass] Student
+# 20| [RecordClass] Student
# 20| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 20| 0: [Parameter] left
@@ -862,7 +862,7 @@ Record.cs:
# 24| 4: [AssignExpr] ... = ...
# 24| 0: [PropertyCall] access to property Level
# 24| 1: [ParameterAccess] access to parameter level
-# 27| [Record,RecordClass] Person1
+# 27| [RecordClass] Person1
# 27| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 27| 0: [Parameter] left
@@ -889,7 +889,7 @@ Record.cs:
# 27| 4: [Setter] set_LastName
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
-# 29| [Record,RecordClass] Teacher1
+# 29| [RecordClass] Teacher1
# 29| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 29| 0: [Parameter] left
@@ -913,7 +913,7 @@ Record.cs:
# 29| 4: [Setter] set_Subject
#-----| 2: (Parameters)
# 29| 0: [Parameter] value
-# 32| [Record,RecordClass] Student1
+# 32| [RecordClass] Student1
# 32| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 32| 0: [Parameter] left
@@ -937,7 +937,7 @@ Record.cs:
# 32| 4: [Setter] set_Level
#-----| 2: (Parameters)
# 32| 0: [Parameter] value
-# 35| [Record,RecordClass] Pet
+# 35| [RecordClass] Pet
# 35| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 35| 0: [Parameter] left
@@ -963,7 +963,7 @@ Record.cs:
# 38| -1: [TypeAccess] access to type Console
# 38| 0: [TypeMention] Console
# 38| 0: [StringLiteral] "Shredding furniture"
-# 41| [Record,RecordClass] Dog
+# 41| [RecordClass] Dog
# 41| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 41| 0: [Parameter] left
@@ -1002,7 +1002,7 @@ Record.cs:
# 50| 0: [MethodCall] call to method ToString
# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteral] " is a dog"
-# 54| [Record,RecordClass] R1
+# 54| [RecordClass] R1
# 54| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 54| 0: [Parameter] left
@@ -1022,7 +1022,7 @@ Record.cs:
# 54| 4: [Setter] set_A
#-----| 2: (Parameters)
# 54| 0: [Parameter] value
-# 56| [Record,RecordClass] R2
+# 56| [RecordClass] R2
# 56| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 56| 0: [Parameter] left
diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs
index 8ac0404cd99..4353d646b49 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/J.cs
+++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs
@@ -31,9 +31,9 @@ public class J
private void M2()
{
- var o = Source(1);
+ var o = Source(2);
var r1 = new RecordStruct(o, null);
- Sink(r1.Prop1); // $ hasValueFlow=1
+ Sink(r1.Prop1); // $ hasValueFlow=2
Sink(r1.Prop2); // no flow
}
From 568d37e9b9cb3af16b60dabde7339435f5030a3e Mon Sep 17 00:00:00 2001
From: Henry Mercer
Date: Mon, 17 Jan 2022 16:32:57 +0000
Subject: [PATCH 045/296] JS: Update definition of ATM query suite
It's simpler to just run all the queries in the pack instead of
specifying the IDs.
---
.../src/codeql-suites/javascript-atm-code-scanning.qls | 6 ------
1 file changed, 6 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls
index 2a5997e9d7a..18a6dce52a1 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/codeql-suites/javascript-atm-code-scanning.qls
@@ -1,8 +1,2 @@
- description: ATM boosted Code Scanning queries for JavaScript
- queries: .
-- include:
- id:
- - adaptive-threat-modeling/js/nosql-injection
- - adaptive-threat-modeling/js/sql-injection
- - adaptive-threat-modeling/js/path-injection
- - adaptive-threat-modeling/js/xss
From e9128466d4a89f770b9486c777b7ac25f6a18c0b Mon Sep 17 00:00:00 2001
From: Henry Mercer
Date: Mon, 17 Jan 2022 16:34:28 +0000
Subject: [PATCH 046/296] JS: Add query help for ML-powered queries
Query help is identical to the original query, except for a new
paragraph prepended to the overview explaining that the queries are
experimental.
We add Markdown query help since only Markdown query help is embedded in
SARIF via `--sarif-add-query-help`.
---
.../src/NosqlInjectionATM.md | 50 +++++++++++++++++++
.../src/SqlInjectionATM.md | 50 +++++++++++++++++++
.../src/TaintedPathATM.md | 42 ++++++++++++++++
.../adaptivethreatmodeling/src/XssATM.md | 32 ++++++++++++
4 files changed, 174 insertions(+)
create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.md
create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.md
create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.md
create mode 100644 javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.md
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.md b/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.md
new file mode 100644
index 00000000000..4097bbae999
--- /dev/null
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/NosqlInjectionATM.md
@@ -0,0 +1,50 @@
+# NoSQL database query built from user-controlled sources (experimental)
+This is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
+
+If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
+
+
+## Recommendation
+Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
+
+For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
+
+
+## Example
+In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
+
+The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
+
+In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.
+
+In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks.
+
+
+```javascript
+const app = require("express")(),
+ pg = require("pg"),
+ pool = new pg.Pool(config);
+
+app.get("search", function handler(req, res) {
+ // BAD: the category might have SQL special characters in it
+ var query1 =
+ "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" +
+ req.params.category +
+ "' ORDER BY PRICE";
+ pool.query(query1, [], function(err, results) {
+ // process results
+ });
+
+ // GOOD: use parameters
+ var query2 =
+ "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE";
+ pool.query(query2, [req.params.category], function(err, results) {
+ // process results
+ });
+});
+
+```
+
+## References
+* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
+* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.md b/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.md
new file mode 100644
index 00000000000..8e1d60534f5
--- /dev/null
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/SqlInjectionATM.md
@@ -0,0 +1,50 @@
+# SQL database query built from user-controlled sources (experimental)
+This is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
+
+If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
+
+
+## Recommendation
+Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
+
+For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
+
+
+## Example
+In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
+
+The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
+
+In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.
+
+In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks.
+
+
+```javascript
+const app = require("express")(),
+ pg = require("pg"),
+ pool = new pg.Pool(config);
+
+app.get("search", function handler(req, res) {
+ // BAD: the category might have SQL special characters in it
+ var query1 =
+ "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" +
+ req.params.category +
+ "' ORDER BY PRICE";
+ pool.query(query1, [], function(err, results) {
+ // process results
+ });
+
+ // GOOD: use parameters
+ var query2 =
+ "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE";
+ pool.query(query2, [req.params.category], function(err, results) {
+ // process results
+ });
+});
+
+```
+
+## References
+* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
+* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.md b/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.md
new file mode 100644
index 00000000000..11424fb295d
--- /dev/null
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/TaintedPathATM.md
@@ -0,0 +1,42 @@
+# Uncontrolled data used in path expression (experimental)
+This is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
+
+Accessing files using paths constructed from user-controlled data can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files.
+
+
+## Recommendation
+Validate user input before using it to construct a file path, either using an off-the-shelf library like the `sanitize-filename` npm package, or by performing custom validation.
+
+Ideally, follow these rules:
+
+* Do not allow more than a single "." character.
+* Do not allow directory separators such as "/" or "\\" (depending on the file system).
+* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//", the resulting string would still be "../".
+* Use a whitelist of known good patterns.
+
+## Example
+In the first example, a file name is read from an HTTP request and then used to access a file. However, a malicious user could enter a file name which is an absolute path, such as `"/etc/passwd"`.
+
+In the second example, it appears that the user is restricted to opening a file within the `"user"` home directory. However, a malicious user could enter a file name containing special characters. For example, the string `"../../etc/passwd"` will result in the code reading the file located at `"/home/user/../../etc/passwd"`, which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords.
+
+
+```javascript
+var fs = require('fs'),
+ http = require('http'),
+ url = require('url');
+
+var server = http.createServer(function(req, res) {
+ let path = url.parse(req.url, true).query.path;
+
+ // BAD: This could read any file on the file system
+ res.write(fs.readFileSync(path));
+
+ // BAD: This could still read any file on the file system
+ res.write(fs.readFileSync("/home/user/" + path));
+});
+
+```
+
+## References
+* OWASP: [Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal).
+* npm: [sanitize-filename](https://www.npmjs.com/package/sanitize-filename) package.
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.md b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.md
new file mode 100644
index 00000000000..c08bf5c485e
--- /dev/null
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.md
@@ -0,0 +1,32 @@
+# Client-side cross-site scripting (experimental)
+This is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
+
+Directly writing user input (for example, a URL query parameter) to a webpage without properly sanitizing the input first, allows for a cross-site scripting vulnerability.
+
+This kind of vulnerability is also called *DOM-based* cross-site scripting, to distinguish it from other types of cross-site scripting.
+
+
+## Recommendation
+To guard against cross-site scripting, consider using contextual output encoding/escaping before writing user input to the page, or one of the other solutions that are mentioned in the references.
+
+
+## Example
+The following example shows part of the page URL being written directly to the document, leaving the website vulnerable to cross-site scripting.
+
+
+```javascript
+function setLanguageOptions() {
+ var href = document.location.href,
+ deflt = href.substring(href.indexOf("default=")+8);
+ document.write(""+deflt+" ");
+ document.write("English ");
+}
+
+```
+
+## References
+* OWASP: [DOM based XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html).
+* OWASP: [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
+* OWASP [DOM Based XSS](https://www.owasp.org/index.php/DOM_Based_XSS).
+* OWASP [Types of Cross-Site Scripting](https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting).
+* Wikipedia: [Cross-site scripting](http://en.wikipedia.org/wiki/Cross-site_scripting).
From e7dde79d50809dcb3ff00b9eae199c13c2e636f7 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Mon, 17 Jan 2022 17:14:58 +0000
Subject: [PATCH 047/296] Add note and link to main CodeQL CLI docs
---
docs/codeql/support/framework-support.rst | 6 ++++++
docs/codeql/support/language-support.rst | 6 ++++++
2 files changed, 12 insertions(+)
diff --git a/docs/codeql/support/framework-support.rst b/docs/codeql/support/framework-support.rst
index 8f9664cf63e..a99bc084a72 100644
--- a/docs/codeql/support/framework-support.rst
+++ b/docs/codeql/support/framework-support.rst
@@ -3,6 +3,12 @@ Frameworks and libraries
LGTM Enterprise |release| includes CodeQL CLI |version|. The CodeQL libraries and queries used by this version of LGTM Enterprise have been explicitly checked against the libraries and frameworks listed below.
+.. pull-quote::
+
+ Note
+
+ For details of language and compiler support in the most recent release of the CodeQL CLI, see `Supported languages and frameworks `__ in the CodeQL CLI documentation.
+
.. pull-quote::
Tip
diff --git a/docs/codeql/support/language-support.rst b/docs/codeql/support/language-support.rst
index 034d5db23f0..49b90693a7c 100644
--- a/docs/codeql/support/language-support.rst
+++ b/docs/codeql/support/language-support.rst
@@ -3,6 +3,12 @@ Languages and compilers
LGTM Enterprise |release| includes CodeQL CLI |version|. LGTM Enterprise supports analysis of the following languages compiled by the following compilers.
+.. pull-quote::
+
+ Note
+
+ For details of language and compiler support in the most recent release of the CodeQL CLI, see `Supported languages and frameworks `__ in the CodeQL CLI documentation.
+
Note that where there are several versions or dialects of a language, the supported variants are listed.
If your code requires a particular version of a compiler, check that this version is included below.
If you have any questions about language and compiler support, you can find help on the `GitHub Security Lab discussions board `__.
From e0110bd25ee3054a5852297fd733192d0002a803 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Mon, 17 Jan 2022 17:20:00 +0000
Subject: [PATCH 048/296] FIx typo in new note
---
docs/codeql/support/framework-support.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/support/framework-support.rst b/docs/codeql/support/framework-support.rst
index a99bc084a72..d12b1a96c8f 100644
--- a/docs/codeql/support/framework-support.rst
+++ b/docs/codeql/support/framework-support.rst
@@ -7,7 +7,7 @@ LGTM Enterprise |release| includes CodeQL CLI |version|. The CodeQL libraries an
Note
- For details of language and compiler support in the most recent release of the CodeQL CLI, see `Supported languages and frameworks `__ in the CodeQL CLI documentation.
+ For details of framework and library support in the most recent release of the CodeQL CLI, see `Supported languages and frameworks `__ in the CodeQL CLI documentation.
.. pull-quote::
From c1a51d94a2b28fa361cff02a82914f57add7850c Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Mon, 17 Jan 2022 17:44:52 +0000
Subject: [PATCH 049/296] Ruby: add test for protect_from_forgery without
exception strategy
---
.../cwe-352/CSRFProtectionDisabled.expected | 9 +++++----
.../app/controllers/application_controller.rb | 18 ++++++++++++++++++
.../app/controllers/articles_controller.rb | 15 +++++++++++++++
.../app/controllers/users_controller.rb | 2 +-
4 files changed, 39 insertions(+), 5 deletions(-)
create mode 100644 ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
diff --git a/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected b/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
index c51f71a04d3..d80c52afc66 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
+++ b/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
@@ -1,4 +1,5 @@
-| railsapp/app/controllers/users_controller.rb:4:3:4:47 | call to skip_before_action | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/application.rb:15:5:15:53 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/environments/development.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/environments/production.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
+| railsapp/app/controllers/application_controller.rb:5:3:5:22 | call to protect_from_forgery | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/app/controllers/users_controller.rb:4:3:4:47 | call to skip_before_action | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/application.rb:15:5:15:53 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/environments/development.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/environments/production.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
index 09705d12ab4..6ff599938e8 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
@@ -1,2 +1,20 @@
class ApplicationController < ActionController::Base
+
+ # BAD: `protect_from_forgery` without `with: :exception` can expose an
+ # application to CSRF attacks in some circumstances
+ protect_from_forgery
+
+ before_action authz_guard
+
+ def current_user
+ @current_user ||= User.find_by_id(session[:user_id])
+ end
+
+ def logged_in?
+ !current_user.nil?
+ end
+
+ def authz_guard
+ render(plain: "not logged in") unless logged_in?
+ end
end
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
new file mode 100644
index 00000000000..2a0037f4b25
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -0,0 +1,15 @@
+class ArticlesController < ApplicationController
+ prepend_before_action :user_authored_article?, only: [:delete_authored_article]
+
+ def delete_authored_article
+ article.destroy
+ end
+
+ def article
+ @article ||= Article.find(params[:article_id])
+ end
+
+ def user_authored_article?
+ @article.author_id = current_user.id
+ end
+end
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
index 138a342b3cb..596a7b0108f 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
@@ -4,7 +4,7 @@ class UsersController < ApplicationController
skip_before_action :verify_authenticity_token
def change_email
- user = User.find_by(name: params[:user_name])
+ user = current_user
user.email = params[:new_email]
user.save!
end
From c9467d7e94e36f0a02b5f9dcfec4fb8fb75bcab7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:32:17 +0100
Subject: [PATCH 050/296] C#: Add new tables to the dbscheme line span pragma.
---
csharp/ql/lib/semmlecode.csharp.dbscheme | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme
index 193c35b0e37..ff083666c7f 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme
@@ -385,7 +385,7 @@ directive_endregions(
directive_lines(
unique int id: @directive_line,
- int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
directive_line_value(
unique int id: @directive_line ref,
@@ -393,8 +393,18 @@ directive_line_value(
directive_line_file(
unique int id: @directive_line ref,
- int file: @file ref
-)
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
directive_nullables(
unique int id: @directive_nullable,
From a197befb5f997a6235929f2f5c69643db94735f1 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:35:03 +0100
Subject: [PATCH 051/296] C#: Add shared base class for line and line span
pragmas.
---
.../LineOrSpanDirective.cs | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
new file mode 100644
index 00000000000..546e1571596
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
@@ -0,0 +1,32 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
+
+namespace Semmle.Extraction.CSharp.Entities
+{
+ internal enum LineDirectiveKind
+ {
+ Default = 0,
+ Hidden = 1,
+ Numeric = 2,
+ Span = 3
+ }
+
+ internal abstract class LineOrSpanDirective : PreprocessorDirective where T : LineOrSpanDirectiveTriviaSyntax
+ {
+ protected LineOrSpanDirective(Context cx, T trivia)
+ : base(cx, trivia)
+ {
+ }
+
+ protected override void PopulatePreprocessor(TextWriter trapFile)
+ {
+ if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
+ {
+ var file = File.Create(Context, Symbol.File.ValueText);
+ trapFile.directive_line_file(this, file);
+ }
+ }
+ }
+}
From 195d40c04e33fc0c26cae654c4d6da8d672c23f7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:37:10 +0100
Subject: [PATCH 052/296] C#: Add new class needed for LineSpanDirective and
modify existing implementation to use the new types.
---
.../PreprocessorDirectives/LineDirective.cs | 16 +++-----
.../LineSpanDirective.cs | 40 +++++++++++++++++++
.../Semmle.Extraction.CSharp/Tuples.cs | 12 ++++--
3 files changed, 55 insertions(+), 13 deletions(-)
create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
index 6afae54a129..d4075a6f4a9 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
@@ -5,7 +5,7 @@ using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
- internal class LineDirective : PreprocessorDirective
+ internal class LineDirective : LineOrSpanDirective
{
private LineDirective(Context cx, LineDirectiveTriviaSyntax trivia)
: base(cx, trivia)
@@ -16,9 +16,9 @@ namespace Semmle.Extraction.CSharp.Entities
{
var type = Symbol.Line.Kind() switch
{
- SyntaxKind.DefaultKeyword => 0,
- SyntaxKind.HiddenKeyword => 1,
- SyntaxKind.NumericLiteralToken => 2,
+ SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
+ SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
+ SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
_ => throw new InternalError(Symbol, "Unhandled line token kind")
};
@@ -28,13 +28,9 @@ namespace Semmle.Extraction.CSharp.Entities
{
var value = (int)Symbol.Line.Value!;
trapFile.directive_line_value(this, value);
-
- if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
- {
- var file = File.Create(Context, Symbol.File.ValueText);
- trapFile.directive_line_file(this, file);
- }
}
+
+ base.PopulatePreprocessor(trapFile);
}
public static LineDirective Create(Context cx, LineDirectiveTriviaSyntax line) =>
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
new file mode 100644
index 00000000000..7d8396d7b04
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
@@ -0,0 +1,40 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
+
+namespace Semmle.Extraction.CSharp.Entities
+{
+ internal class LineSpanDirective : LineOrSpanDirective
+ {
+ private LineSpanDirective(Context cx, LineSpanDirectiveTriviaSyntax trivia)
+ : base(cx, trivia) { }
+ public static LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax line) =>
+ LineSpanDirectiveFactory.Instance.CreateEntity(cx, line, line);
+
+ protected override void PopulatePreprocessor(TextWriter trapFile)
+ {
+ trapFile.directive_lines(this, LineDirectiveKind.Span);
+
+ var startLine = (int)Symbol.Start.Line.Value!;
+ var startColumn = (int)Symbol.Start.Character.Value!;
+ var endLine = (int)Symbol.End.Line.Value!;
+ var endColumn = (int)Symbol.End.Character.Value!;
+ trapFile.directive_line_span(this, startLine, startColumn, endLine, endColumn);
+
+ var offset = Symbol.CharacterOffset.Value;
+ if (offset is not null)
+ {
+ trapFile.directive_line_offset(this, (int)offset);
+ }
+ base.PopulatePreprocessor(trapFile);
+ }
+
+ private class LineSpanDirectiveFactory : CachedEntityFactory
+ {
+ public static LineSpanDirectiveFactory Instance { get; } = new LineSpanDirectiveFactory();
+
+ public override LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax init) => new(cx, init);
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
index 028a0259a55..225c11ada22 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
@@ -413,15 +413,21 @@ namespace Semmle.Extraction.CSharp
internal static void directive_nullables(this TextWriter trapFile, NullableDirective directive, int setting, int target) =>
trapFile.WriteTuple("directive_nullables", directive, setting, target);
- internal static void directive_lines(this TextWriter trapFile, LineDirective directive, int kind) =>
- trapFile.WriteTuple("directive_lines", directive, kind);
+ internal static void directive_lines(this TextWriter trapFile, LineOrSpanDirective directive, LineDirectiveKind kind) where T : LineOrSpanDirectiveTriviaSyntax =>
+ trapFile.WriteTuple("directive_lines", directive, (int)kind);
internal static void directive_line_value(this TextWriter trapFile, LineDirective directive, int line) =>
trapFile.WriteTuple("directive_line_value", directive, line);
- internal static void directive_line_file(this TextWriter trapFile, LineDirective directive, Extraction.Entities.File file) =>
+ internal static void directive_line_file(this TextWriter trapFile, LineOrSpanDirective directive, Extraction.Entities.File file) where T : LineOrSpanDirectiveTriviaSyntax =>
trapFile.WriteTuple("directive_line_file", directive, file);
+ internal static void directive_line_offset(this TextWriter trapFile, LineSpanDirective directive, int offset) =>
+ trapFile.WriteTuple("directive_line_offset", directive, offset);
+
+ internal static void directive_line_span(this TextWriter trapFile, LineSpanDirective directive, int startLine, int startColumn, int endLine, int endColumn) =>
+ trapFile.WriteTuple("directive_line_span", directive, startLine, startColumn, endLine, endColumn);
+
internal static void directive_regions(this TextWriter trapFile, RegionDirective directive, string name) =>
trapFile.WriteTuple("directive_regions", directive, name);
From af380f846e79bddc8944e6f40d8c16f6a18c9b6d Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:37:44 +0100
Subject: [PATCH 053/296] C#: Add support in the extractor for the
LineSpanDirective.
---
.../Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
index 49b1e96990a..273853cb320 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
@@ -62,6 +62,9 @@ namespace Semmle.Extraction.CSharp.Populators
Entities.LineDirective.Create(cx, node);
}
+ public override void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) =>
+ Entities.LineSpanDirective.Create(cx, node);
+
private readonly Stack regionStarts = new Stack();
public override void VisitRegionDirectiveTrivia(RegionDirectiveTriviaSyntax node)
From 7e264668d8b7c2cbba814696fdac94d62ec61b0b Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:43:41 +0100
Subject: [PATCH 054/296] C#: Refator directive visitor to use expression body.
---
.../Populators/DirectiveVisitor.cs | 36 +++++--------------
1 file changed, 9 insertions(+), 27 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
index 273853cb320..9df04a7cfa5 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
@@ -17,50 +17,32 @@ namespace Semmle.Extraction.CSharp.Populators
///
public IEnumerable BranchesTaken => branchesTaken;
- public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia)
- {
+ public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia) =>
this.cx = cx;
- }
- public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node)
- {
+ public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) =>
Entities.PragmaWarningDirective.Create(cx, node);
- }
- public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node)
- {
+ public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) =>
Entities.PragmaChecksumDirective.Create(cx, node);
- }
- public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node)
- {
+ public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) =>
Entities.DefineDirective.Create(cx, node);
- }
- public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node)
- {
+ public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) =>
Entities.UndefineDirective.Create(cx, node);
- }
- public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node)
- {
+ public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node) =>
Entities.WarningDirective.Create(cx, node);
- }
- public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node)
- {
+ public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node) =>
Entities.ErrorDirective.Create(cx, node);
- }
- public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
- {
+ public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) =>
Entities.NullableDirective.Create(cx, node);
- }
- public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node)
- {
+ public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) =>
Entities.LineDirective.Create(cx, node);
- }
public override void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) =>
Entities.LineSpanDirective.Create(cx, node);
From 93255dfe1391d9250661871229e43d7167101c11 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:38:26 +0100
Subject: [PATCH 055/296] C#: Add QL library support for the Line span
directive.
---
.../lib/semmle/code/csharp/Preprocessor.qll | 29 +++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
index 3342dd5c59c..ac6408440e8 100644
--- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
@@ -208,21 +208,40 @@ class HiddenLineDirective extends LineDirective {
override string getAPrimaryQlClass() { result = "HiddenLineDirective" }
}
+abstract private class NumericOrSpanLineDirective extends LineDirective {
+ /** Gets the referenced file of this directive. */
+ File getReferencedFile() { directive_line_file(this, result) }
+}
+
/**
- * A numeric `#line` directive, such as `#line 200 file`
+ * A numeric `#line` directive, such as `#line 200 file`.
*/
-class NumericLineDirective extends LineDirective {
+class NumericLineDirective extends NumericOrSpanLineDirective {
NumericLineDirective() { directive_lines(this, 2) }
/** Gets the line number of this directive. */
int getLine() { directive_line_value(this, result) }
- /** Gets the referenced file of this directive. */
- File getReferencedFile() { directive_line_file(this, result) }
-
override string getAPrimaryQlClass() { result = "NumericLineDirective" }
}
+/**
+ * A line span `#line` directive, such as `#line (1, 1) - (3, 10) 5 file`.
+ */
+class SpanLineDirective extends NumericOrSpanLineDirective {
+ SpanLineDirective() { directive_lines(this, 3) }
+
+ /** Gets the offset of this directive. */
+ int getOffset() { directive_line_offset(this, result) }
+
+ /** Gets the span of this directive. */
+ predicate span(int startLine, int startColumn, int endLine, int endColumn) {
+ directive_line_span(this, startLine, startColumn, endLine, endColumn)
+ }
+
+ override string getAPrimaryQlClass() { result = "SpanLineDirective" }
+}
+
/**
* A `#region` directive.
*/
From 8b048ca17e31f8c9259a63108d6714a0d7fa89cc Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:39:31 +0100
Subject: [PATCH 056/296] C#: Add line span pragma example.
---
csharp/ql/test/library-tests/csharp10/LinePragmas.cs | 12 ++++++++++++
.../test/library-tests/csharp10/LinePragmasRef1.cs | 0
.../test/library-tests/csharp10/LinePragmasRef2.cs | 0
3 files changed, 12 insertions(+)
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmas.cs
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmas.cs b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs
new file mode 100644
index 00000000000..73fff46f6fc
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs
@@ -0,0 +1,12 @@
+using System;
+
+public class MyLineDirective
+{
+ public static void M1()
+ {
+#line (1, 1) - (1, 30) 5 "LinePragmasRef1.cs"
+ int i = 0;
+#line (2, 1) - (5, 32) "LinePragmasRef2.cs"
+ int j = 0;
+ }
+}
\ No newline at end of file
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs
new file mode 100644
index 00000000000..e69de29bb2d
From ac47c96f48df6a12fd0f8097b3931eeecfbbf3fd Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:40:07 +0100
Subject: [PATCH 057/296] C#: Add Line span pragma test case.
---
.../library-tests/csharp10/linePragmas.expected | 5 +++++
.../ql/test/library-tests/csharp10/linePragmas.ql | 13 +++++++++++++
2 files changed, 18 insertions(+)
create mode 100644 csharp/ql/test/library-tests/csharp10/linePragmas.expected
create mode 100644 csharp/ql/test/library-tests/csharp10/linePragmas.ql
diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.expected b/csharp/ql/test/library-tests/csharp10/linePragmas.expected
new file mode 100644
index 00000000000..2d88fa7582f
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/linePragmas.expected
@@ -0,0 +1,5 @@
+linespan_directives
+| LinePragmas.cs:7:1:7:45 | #line ... | 1 | 1 | 1 | 30 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs |
+| LinePragmas.cs:9:1:9:43 | #line ... | 2 | 1 | 5 | 32 | LinePragmasRef2.cs:0:0:0:0 | LinePragmasRef2.cs |
+linespan_offset
+| LinePragmas.cs:7:1:7:45 | #line ... | 5 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs |
diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.ql b/csharp/ql/test/library-tests/csharp10/linePragmas.ql
new file mode 100644
index 00000000000..41bf0a60d31
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/linePragmas.ql
@@ -0,0 +1,13 @@
+import csharp
+
+query predicate linespan_directives(
+ SpanLineDirective directive, int startLine, int startColumn, int endLine, int endColumn, File file
+) {
+ file = directive.getReferencedFile() and
+ directive.span(startLine, startColumn, endLine, endColumn)
+}
+
+query predicate linespan_offset(SpanLineDirective directive, int offset, File file) {
+ file = directive.getReferencedFile() and
+ offset = directive.getOffset()
+}
From 8fd116fbd7d0fc0c26f60bf247a9bbd71a9423e3 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 09:38:39 +0100
Subject: [PATCH 058/296] C#: Add upgrade scripts for the new tables requires
for the line span pragma.
---
.../old.dbscheme | 2088 ++++++++++++++++
.../semmlecode.csharp.dbscheme | 2098 +++++++++++++++++
.../upgrade.properties | 2 +
3 files changed, 4188 insertions(+)
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
diff --git a/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
new file mode 100644
index 00000000000..193c35b0e37
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
@@ -0,0 +1,2088 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * 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);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: 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_global(
+ unique int id: @using_directive ref
+);
+
+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/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
new file mode 100644
index 00000000000..ff083666c7f
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
@@ -0,0 +1,2098 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * 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);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: 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_global(
+ unique int id: @using_directive ref
+);
+
+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, 3: span */
+
+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_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int 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/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
new file mode 100644
index 00000000000..31163274055
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
@@ -0,0 +1,2 @@
+description: Add support for line span pragma.
+compatibility: backwards
From bf210267712183e0244bdbedbdf1d56757b1eb5c Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 09:46:07 +0100
Subject: [PATCH 059/296] C#: Add downgrade scripts for the line span pragma.
---
.../old.dbscheme | 2098 +++++++++++++++++
.../semmlecode.csharp.dbscheme | 2088 ++++++++++++++++
.../upgrade.properties | 5 +
3 files changed, 4191 insertions(+)
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
diff --git a/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
new file mode 100644
index 00000000000..ff083666c7f
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
@@ -0,0 +1,2098 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * 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);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: 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_global(
+ unique int id: @using_directive ref
+);
+
+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, 3: span */
+
+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_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int 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/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
new file mode 100644
index 00000000000..193c35b0e37
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
@@ -0,0 +1,2088 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * 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);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: 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_global(
+ unique int id: @using_directive ref
+);
+
+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/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
new file mode 100644
index 00000000000..47cd8720ce9
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
@@ -0,0 +1,5 @@
+description: Remove support for line span pragma.
+compatibility: backwards
+directive_line_offset.rel: delete
+directive_line_span.rel: delete
+
From de3d62b3f4d6f9e50a4e4ff21f95fa754bc067b2 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 09:33:40 +0100
Subject: [PATCH 060/296] C#: Update stats file for the new relations (they are
unfortunately empty).
---
.../ql/lib/semmlecode.csharp.dbscheme.stats | 3403 +++++++++--------
1 file changed, 1851 insertions(+), 1552 deletions(-)
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
index 46d7b963528..f458da72beb 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
@@ -42,11 +42,11 @@
@folder
- 484046
+ 484045
@namespace
- 367576
+ 367575
@namespace_declaration
@@ -174,19 +174,19 @@
@struct_type
- 1223176
+ 1223173
@class_type
- 3789357
+ 3789350
@interface_type
- 2384809
+ 2384805
@delegate_type
- 2249826
+ 2249822
@null_type
@@ -194,7 +194,7 @@
@type_parameter
- 831792
+ 831790
@pointer_type
@@ -242,23 +242,23 @@
@typeref
- 3537567
-
-
- @location_default
- 43578550
+ 3537560
@attribute
- 10551347
+ 10551328
@type_mention
- 4147997
+ 4147990
+
+
+ @location_default
+ 43578472
@oblivious
- 15642
+ 15641
@not_annotated
@@ -270,7 +270,7 @@
@type_parameter_constraints
- 1730282
+ 1730279
@modifier
@@ -278,7 +278,7 @@
@property
- 4879894
+ 4879885
@indexer
@@ -286,11 +286,11 @@
@getter
- 4950272
+ 4950263
@setter
- 864801
+ 864799
@event
@@ -306,15 +306,15 @@
@operator
- 807643
+ 807641
@method
- 15027131
+ 15027104
@constructor
- 4401500
+ 4401492
@destructor
@@ -326,15 +326,15 @@
@addressable_field
- 8156775
+ 8156760
@constant
- 2845825
+ 2845820
@addressable_local_variable
- 353480
+ 353479
@local_constant
@@ -346,15 +346,15 @@
@parameter
- 27466281
+ 27466231
@block_stmt
- 470421
+ 470420
@expr_stmt
- 493565
+ 493564
@if_stmt
@@ -382,7 +382,7 @@
@break_stmt
- 42189
+ 42188
@continue_stmt
@@ -390,7 +390,7 @@
@goto_stmt
- 3587
+ 3586
@goto_case_stmt
@@ -466,7 +466,7 @@
@local_function_stmt
- 3317
+ 3316
@using_decl_stmt
@@ -474,7 +474,7 @@
@bool_literal_expr
- 585969
+ 585968
@char_literal_expr
@@ -482,7 +482,7 @@
@int_literal_expr
- 3350910
+ 3350904
@long_literal_expr
@@ -506,11 +506,11 @@
@string_literal_expr
- 1548385
+ 1548382
@null_literal_expr
- 155827
+ 155826
@this_access_expr
@@ -522,11 +522,11 @@
@local_variable_access_expr
- 1030138
+ 1030136
@parameter_access_expr
- 969868
+ 969866
@field_access_expr
@@ -534,7 +534,7 @@
@property_access_expr
- 1360056
+ 1360054
@method_access_expr
@@ -554,15 +554,15 @@
@type_access_expr
- 919476
+ 919474
@typeof_expr
- 439082
+ 439081
@method_invocation_expr
- 832881
+ 832863
@delegate_invocation_expr
@@ -570,15 +570,15 @@
@operator_invocation_expr
- 778750
+ 778748
@cast_expr
- 540190
+ 540196
@object_creation_expr
- 438905
+ 438904
@explicit_delegate_creation_expr
@@ -590,11 +590,11 @@
@array_creation_expr
- 349824
+ 349823
@default_expr
- 790760
+ 790758
@minus_expr
@@ -710,7 +710,7 @@
@simple_assign_expr
- 1592072
+ 1592070
@assign_add_expr
@@ -730,7 +730,7 @@
@object_init_expr
- 383017
+ 383016
@collection_init_expr
@@ -762,11 +762,11 @@
@local_var_decl_expr
- 354491
+ 354490
@lambda_expr
- 733508
+ 733506
@anonymous_method_expr
@@ -802,7 +802,7 @@
@decimal_literal_expr
- 131181
+ 131180
@plus_expr
@@ -958,11 +958,11 @@
@xmlelement
- 1042734675
+ 1042732803
@xmlattribute
- 782957811
+ 782956405
@xmlnamespace
@@ -974,7 +974,7 @@
@xmlcharacters
- 808544061
+ 808542609
@singlelinecomment
@@ -982,7 +982,7 @@
@xmldoccomment
- 1212394
+ 1212392
@multilinecomment
@@ -990,7 +990,7 @@
@commentblock
- 412296
+ 412295
@asp_close_tag
@@ -1030,11 +1030,11 @@
@cil_valueorreftype
- 7660331
+ 7660317
@cil_typeparameter
- 1302994
+ 1302992
@cil_array_type
@@ -1050,11 +1050,11 @@
@cil_method
- 28926216
+ 28926164
@cil_ceq
- 683258
+ 683257
@cil_cgt
@@ -1062,11 +1062,11 @@
@cil_cgt_un
- 260989
+ 260988
@cil_clt
- 55669
+ 55668
@cil_clt_un
@@ -1074,7 +1074,7 @@
@cil_ldftn
- 2118027
+ 2118023
@cil_ldvirtftn
@@ -1110,11 +1110,11 @@
@cil_initobj
- 698444
+ 698443
@cil_constrained
- 557146
+ 557145
@cil_cpblk
@@ -1138,7 +1138,7 @@
@cil_stsfld
- 1909496
+ 1909493
@cil_stobj
@@ -1146,19 +1146,19 @@
@cil_box
- 1043089
+ 1043087
@cil_newarr
- 1178162
+ 1178159
@cil_ldlen
- 418971
+ 418970
@cil_ldelema
- 524864
+ 524863
@cil_ldelem_i1
@@ -1202,7 +1202,7 @@
@cil_ldelem_ref
- 253309
+ 253308
@cil_stelem_i
@@ -1230,7 +1230,7 @@
@cil_stelem_ref
- 3101391
+ 3101385
@cil_ldelem
@@ -1258,7 +1258,7 @@
@cil_ldtoken
- 749623
+ 749621
@cil_conv_u2
@@ -1266,7 +1266,7 @@
@cil_conv_u1
- 175034
+ 175033
@cil_conv_i
@@ -1290,15 +1290,15 @@
@cil_endfinally
- 1445725
+ 1445722
@cil_leave
- 508918
+ 508917
@cil_leave_s
- 2302564
+ 2302560
@cil_stind_i
@@ -1310,131 +1310,131 @@
@cil_nop
- 1547248
+ 1547241
@cil_ldarg_0
- 39364252
+ 39364181
@cil_ldarg_1
- 15405533
+ 15405506
@cil_ldarg_2
- 5488999
+ 5488989
@cil_ldarg_3
- 2376435
+ 2376431
@cil_ldloc_0
- 12928933
+ 12928909
@cil_ldloc_1
- 6975728
+ 6975715
@cil_ldloc_2
- 4951075
+ 4951066
@cil_ldloc_3
- 3108312
+ 3108306
@cil_stloc_0
- 6417366
+ 6417355
@cil_stloc_1
- 3676175
+ 3676168
@cil_stloc_2
- 2658099
+ 2658095
@cil_stloc_3
- 1822152
+ 1822149
@cil_ldarg_s
- 2508752
+ 2508747
@cil_ldarga_s
- 917085
+ 917084
@cil_starg_s
- 198638
+ 198637
@cil_ldloc_s
- 10621053
+ 10621034
@cil_ldloca_s
- 7189487
+ 7189474
@cil_stloc_s
- 6640346
+ 6640335
@cil_ldnull
- 5392406
+ 5392397
@cil_ldc_i4_m1
- 640280
+ 640279
@cil_ldc_i4_0
- 7980548
+ 7980533
@cil_ldc_i4_1
- 6322972
+ 6322961
@cil_ldc_i4_2
- 1431536
+ 1431534
@cil_ldc_i4_3
- 788673
+ 788672
@cil_ldc_i4_4
- 724283
+ 724282
@cil_ldc_i4_5
- 424937
+ 424936
@cil_ldc_i4_6
- 245434
+ 245433
@cil_ldc_i4_7
- 218055
+ 218054
@cil_ldc_i4_8
- 326616
+ 326615
@cil_ldc_i4_s
- 3951635
+ 3951628
@cil_ldc_i4
- 2083966
+ 2083962
@cil_ldc_i8
@@ -1442,7 +1442,7 @@
@cil_ldc_r4
- 22823
+ 22822
@cil_ldc_r8
@@ -1450,15 +1450,15 @@
@cil_dup
- 6812192
+ 6812179
@cil_pop
- 2850598
+ 2850593
@cil_call
- 35891791
+ 35891726
@cil_calli
@@ -1466,23 +1466,23 @@
@cil_ret
- 23260143
+ 23260101
@cil_br_s
- 4244082
+ 4244074
@cil_brfalse_s
- 7354021
+ 7354008
@cil_brtrue_s
- 6868468
+ 6868456
@cil_beq_s
- 1166967
+ 1166965
@cil_bge_s
@@ -1494,15 +1494,15 @@
@cil_ble_s
- 251335
+ 251334
@cil_blt_s
- 426846
+ 426845
@cil_bne_un_s
- 1697190
+ 1697187
@cil_bge_un_s
@@ -1522,19 +1522,19 @@
@cil_br
- 1052158
+ 1052156
@cil_brfalse
- 700831
+ 700830
@cil_brtrue
- 590512
+ 590511
@cil_beq
- 308566
+ 308565
@cil_bge
@@ -1542,7 +1542,7 @@
@cil_bgt
- 26164
+ 26163
@cil_ble
@@ -1626,7 +1626,7 @@
@cil_stind_i4
- 324338
+ 324337
@cil_stind_i8
@@ -1642,15 +1642,15 @@
@cil_add
- 1977553
+ 1977549
@cil_sub
- 739882
+ 739880
@cil_mul
- 313317
+ 313316
@cil_div
@@ -1670,11 +1670,11 @@
@cil_and
- 371763
+ 371762
@cil_or
- 165879
+ 165878
@cil_xor
@@ -1710,7 +1710,7 @@
@cil_conv_i4
- 392308
+ 392307
@cil_conv_i8
@@ -1734,7 +1734,7 @@
@cil_callvirt
- 30280801
+ 30280746
@cil_cpobj
@@ -1746,19 +1746,19 @@
@cil_ldstr
- 8268547
+ 8268532
@cil_newobj
- 9351013
+ 9350996
@cil_castclass
- 1325296
+ 1325294
@cil_isinst
- 2016430
+ 2016426
@cil_conv_r_un
@@ -1770,23 +1770,23 @@
@cil_throw
- 5164351
+ 5164341
@cil_ldfld
- 16903695
+ 16903665
@cil_ldflda
- 1433641
+ 1433638
@cil_stfld
- 8348623
+ 8348608
@cil_ldsfld
- 7724179
+ 7724165
@cil_ldsflda
@@ -1926,19 +1926,19 @@
@cil_method_implementation
- 19889366
+ 19889330
@cil_field
- 11684992
+ 11684971
@cil_parameter
- 55186717
+ 55186618
@cil_property
- 4409961
+ 4409953
@cil_event
@@ -1946,7 +1946,7 @@
@cil_local_variable
- 16916582
+ 16916551
@cil_catch_handler
@@ -1958,15 +1958,15 @@
@cil_finally_handler
- 1221334
+ 1221332
@cil_fault_handler
- 224390
+ 224389
@cil_attribute
- 4315762
+ 4315754
@@ -2677,7 +2677,7 @@
compilation_referencing_files
- 523639
+ 523638
id
@@ -2921,57 +2921,57 @@
5
6
- 1143
+ 774
6
7
- 497
+ 866
7
16
- 304
+ 322
16
20
- 451
+ 433
20
- 24
- 424
+ 25
+ 442
- 24
- 30
- 451
+ 25
+ 29
+ 433
- 30
+ 29
46
- 460
+ 424
46
- 55
- 387
-
-
- 55
- 58
- 507
-
-
- 58
- 63
+ 56
424
+
+ 56
+ 59
+ 451
+
+
+ 59
+ 63
+ 405
+
63
- 65
- 64
+ 66
+ 138
@@ -3048,62 +3048,67 @@
2
5
- 460
+ 451
5
6
- 294
+ 350
6
7
- 755
+ 691
7
10
- 488
+ 497
10
15
- 479
+ 516
15
20
- 516
+ 507
20
- 26
- 433
+ 25
+ 451
- 26
- 31
+ 25
+ 35
460
- 31
- 57
- 553
+ 35
+ 58
+ 387
- 57
+ 58
59
- 414
+ 276
59
- 61
+ 60
+ 350
+
+
+ 60
+ 63
460
- 61
- 68
- 175
+ 63
+ 67
+ 92
@@ -3129,7 +3134,7 @@
seconds
- 7817
+ 8333
@@ -3172,15 +3177,10 @@
12
-
- 6
- 7
- 9
-
7
8
- 1613
+ 1622
@@ -3226,8 +3226,8 @@
12
- 848
- 849
+ 904
+ 905
9
@@ -3273,24 +3273,24 @@
12
-
- 116
- 117
- 9
-
-
- 118
- 119
- 9
-
125
126
9
- 135
- 136
+ 130
+ 131
+ 9
+
+
+ 140
+ 141
+ 9
+
+
+ 144
+ 145
9
@@ -3312,22 +3312,22 @@
1
2
- 6102
+ 6664
2
3
- 700
+ 912
3
- 4
- 488
+ 6
+ 728
- 4
+ 6
8
- 525
+ 27
@@ -3343,7 +3343,7 @@
1
2
- 7817
+ 8333
@@ -3359,17 +3359,17 @@
1
2
- 6416
+ 6996
2
3
- 1198
+ 1179
3
- 4
- 202
+ 5
+ 156
@@ -5493,7 +5493,7 @@
cpu_seconds
- 1364
+ 1438
elapsed_seconds
@@ -5543,17 +5543,17 @@
1
2
- 1143
+ 1272
2
3
- 184
+ 147
3
4
- 36
+ 18
@@ -5569,17 +5569,17 @@
1
2
- 1143
+ 1272
2
3
- 184
+ 147
3
4
- 36
+ 18
@@ -6765,11 +6765,11 @@
locations_default
- 43578550
+ 43578472
id
- 43578550
+ 43578472
file
@@ -6777,7 +6777,7 @@
beginLine
- 2347256
+ 2347252
beginColumn
@@ -6785,7 +6785,7 @@
endLine
- 2511837
+ 2511832
endColumn
@@ -6803,7 +6803,7 @@
1
2
- 43578550
+ 43578472
@@ -6819,7 +6819,7 @@
1
2
- 43578550
+ 43578472
@@ -6835,7 +6835,7 @@
1
2
- 43578550
+ 43578472
@@ -6851,7 +6851,7 @@
1
2
- 43578550
+ 43578472
@@ -6867,7 +6867,7 @@
1
2
- 43578550
+ 43578472
@@ -7283,7 +7283,7 @@
2
3
- 443707
+ 443706
3
@@ -7298,12 +7298,12 @@
5
6
- 177016
+ 177015
6
7
- 184061
+ 184060
7
@@ -7328,12 +7328,12 @@
24
92
- 176252
+ 176251
92
759
- 128380
+ 128379
@@ -7349,22 +7349,22 @@
1
2
- 1044823
+ 1044821
2
3
- 387177
+ 387176
3
4
- 354923
+ 354922
4
6
- 187923
+ 187922
6
@@ -7395,7 +7395,7 @@
1
2
- 333364
+ 333363
2
@@ -7425,22 +7425,22 @@
7
9
- 173833
+ 173832
9
13
- 185037
+ 185036
13
24
- 183000
+ 182999
24
98
- 176252
+ 176251
98
@@ -7461,12 +7461,12 @@
1
2
- 1025258
+ 1025256
2
3
- 731193
+ 731192
3
@@ -7476,7 +7476,7 @@
4
6
- 188984
+ 188983
6
@@ -7502,7 +7502,7 @@
2
3
- 443919
+ 443918
3
@@ -7512,7 +7512,7 @@
4
5
- 278574
+ 278573
5
@@ -7527,17 +7527,17 @@
7
8
- 134067
+ 134066
8
10
- 178289
+ 178288
10
14
- 184740
+ 184739
14
@@ -7903,7 +7903,7 @@
3
4
- 280187
+ 280186
4
@@ -7959,7 +7959,7 @@
1
2
- 1096387
+ 1096385
2
@@ -7969,12 +7969,12 @@
3
4
- 490560
+ 490559
4
6
- 207700
+ 207699
6
@@ -7984,7 +7984,7 @@
12
61
- 189748
+ 189747
61
@@ -8005,12 +8005,12 @@
1
2
- 1365582
+ 1365580
2
3
- 545987
+ 545986
3
@@ -8041,17 +8041,17 @@
1
2
- 483133
+ 483132
2
3
- 397193
+ 397192
3
4
- 212156
+ 212155
4
@@ -8071,22 +8071,22 @@
7
9
- 200952
+ 200951
9
13
- 204814
+ 204813
13
24
- 191106
+ 191105
24
126
- 188517
+ 188516
128
@@ -8107,7 +8107,7 @@
1
2
- 440948
+ 440947
2
@@ -8127,7 +8127,7 @@
5
6
- 219583
+ 219582
6
@@ -8244,7 +8244,7 @@
1
2
- 14769
+ 14768
2
@@ -8264,7 +8264,7 @@
6
11
- 4923
+ 4922
11
@@ -8555,11 +8555,11 @@
numlines
- 1043663828
+ 1043661954
element_id
- 1043663828
+ 1043661954
num_lines
@@ -8567,7 +8567,7 @@
num_code
- 243293
+ 243292
num_comment
@@ -8585,7 +8585,7 @@
1
2
- 1043663828
+ 1043661954
@@ -8601,7 +8601,7 @@
1
2
- 1043663828
+ 1043661954
@@ -8617,7 +8617,7 @@
1
2
- 1043663828
+ 1043661954
@@ -9492,15 +9492,15 @@
folders
- 484046
+ 484045
id
- 484046
+ 484045
name
- 484046
+ 484045
@@ -9514,7 +9514,7 @@
1
2
- 484046
+ 484045
@@ -9530,7 +9530,7 @@
1
2
- 484046
+ 484045
@@ -9540,15 +9540,15 @@
containerparent
- 992135
+ 992133
parent
- 484046
+ 484045
child
- 992135
+ 992133
@@ -9562,7 +9562,7 @@
1
2
- 379754
+ 379753
2
@@ -9593,7 +9593,7 @@
1
2
- 992135
+ 992133
@@ -9651,11 +9651,11 @@
namespaces
- 367576
+ 367575
id
- 367576
+ 367575
name
@@ -9673,7 +9673,7 @@
1
2
- 367576
+ 367575
@@ -9870,15 +9870,15 @@
parent_namespace
- 7241099
+ 7241086
child_id
- 7241099
+ 7241086
namespace_id
- 231289
+ 231288
@@ -9892,7 +9892,7 @@
1
2
- 7241099
+ 7241086
@@ -9933,7 +9933,7 @@
6
8
- 17703
+ 17702
8
@@ -9953,7 +9953,7 @@
44
84811
- 13082
+ 13081
@@ -11615,6 +11615,300 @@
+
+ directive_line_offset
+ 0
+
+
+ id
+ 0
+
+
+ offset
+ 0
+
+
+
+
+ id
+ offset
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ offset
+ id
+
+
+ 12
+
+
+
+
+
+
+
+ directive_line_span
+ 0
+
+
+ id
+ 0
+
+
+ startLine
+ 0
+
+
+ startColumn
+ 0
+
+
+ endLine
+ 0
+
+
+ endColumn
+ 0
+
+
+
+
+ id
+ startLine
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ startColumn
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ endLine
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ endColumn
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ startLine
+ id
+
+
+ 12
+
+
+
+
+
+ startLine
+ startColumn
+
+
+ 12
+
+
+
+
+
+ startLine
+ endLine
+
+
+ 12
+
+
+
+
+
+ startLine
+ endColumn
+
+
+ 12
+
+
+
+
+
+ startColumn
+ id
+
+
+ 12
+
+
+
+
+
+ startColumn
+ startLine
+
+
+ 12
+
+
+
+
+
+ startColumn
+ endLine
+
+
+ 12
+
+
+
+
+
+ startColumn
+ endColumn
+
+
+ 12
+
+
+
+
+
+ endLine
+ id
+
+
+ 12
+
+
+
+
+
+ endLine
+ startLine
+
+
+ 12
+
+
+
+
+
+ endLine
+ startColumn
+
+
+ 12
+
+
+
+
+
+ endLine
+ endColumn
+
+
+ 12
+
+
+
+
+
+ endColumn
+ id
+
+
+ 12
+
+
+
+
+
+ endColumn
+ startLine
+
+
+ 12
+
+
+
+
+
+ endColumn
+ startColumn
+
+
+ 12
+
+
+
+
+
+ endColumn
+ endLine
+
+
+ 12
+
+
+
+
+
+
directive_nullables
3382
@@ -12590,11 +12884,11 @@
types
- 8463411
+ 8463395
id
- 8463411
+ 8463395
kind
@@ -12602,7 +12896,7 @@
name
- 2569129
+ 2569124
@@ -12616,7 +12910,7 @@
1
2
- 8463411
+ 8463395
@@ -12632,7 +12926,7 @@
1
2
- 8463411
+ 8463395
@@ -12735,7 +13029,7 @@
1
2
- 2307988
+ 2307983
2
@@ -12761,7 +13055,7 @@
1
2
- 2548128
+ 2548124
2
@@ -12776,15 +13070,15 @@
typerefs
- 3537567
+ 3537560
id
- 3537567
+ 3537560
name
- 2476079
+ 2476075
@@ -12798,7 +13092,7 @@
1
2
- 3537567
+ 3537560
@@ -12814,7 +13108,7 @@
1
2
- 2298312
+ 2298307
2
@@ -12829,15 +13123,15 @@
typeref_type
- 3508083
+ 3508077
id
- 3508083
+ 3508077
typeId
- 3508083
+ 3508077
@@ -12851,7 +13145,7 @@
1
2
- 3508083
+ 3508077
@@ -12867,7 +13161,7 @@
1
2
- 3508083
+ 3508077
@@ -13332,15 +13626,15 @@
delegate_return_type
- 2249826
+ 2249822
delegate_id
- 2249826
+ 2249822
return_type_id
- 801531
+ 801529
@@ -13354,7 +13648,7 @@
1
2
- 2249826
+ 2249822
@@ -13370,7 +13664,7 @@
1
2
- 730409
+ 730408
2
@@ -13458,11 +13752,11 @@
extend
- 3548527
+ 3548520
sub
- 3547415
+ 3547409
super
@@ -13480,7 +13774,7 @@
1
2
- 3546304
+ 3546298
2
@@ -13552,15 +13846,15 @@
implement
- 9498668
+ 9498651
sub
- 3317494
+ 3317488
super
- 2026887
+ 2026883
@@ -13574,27 +13868,27 @@
1
2
- 1125942
+ 1125940
2
3
- 905522
+ 905520
3
4
- 620560
+ 620559
4
6
- 270036
+ 270035
6
9
- 249057
+ 249056
9
@@ -13615,12 +13909,12 @@
1
2
- 973058
+ 973056
2
3
- 598995
+ 598994
3
@@ -13635,7 +13929,7 @@
6
90747
- 122923
+ 122922
@@ -13645,11 +13939,11 @@
type_location
- 4526766
+ 4526758
id
- 4460402
+ 4460394
loc
@@ -13667,7 +13961,7 @@
1
2
- 4438121
+ 4438113
2
@@ -13796,7 +14090,7 @@
tuple_element
- 149836
+ 149835
tuple
@@ -13808,7 +14102,7 @@
field
- 149836
+ 149835
@@ -14186,7 +14480,7 @@
1
2
- 149836
+ 149835
@@ -14202,7 +14496,7 @@
1
2
- 149836
+ 149835
@@ -14212,11 +14506,11 @@
attributes
- 10551347
+ 10551328
id
- 10551347
+ 10551328
type_id
@@ -14224,7 +14518,7 @@
target
- 9250913
+ 9250896
@@ -14238,7 +14532,7 @@
1
2
- 10551347
+ 10551328
@@ -14254,7 +14548,7 @@
1
2
- 10551347
+ 10551328
@@ -14422,12 +14716,12 @@
1
2
- 8608463
+ 8608447
2
3520
- 642450
+ 642449
@@ -14443,12 +14737,12 @@
1
2
- 8733902
+ 8733887
2
29
- 517010
+ 517009
@@ -14458,11 +14752,11 @@
attribute_location
- 10552714
+ 10552695
id
- 10551347
+ 10551328
loc
@@ -14480,7 +14774,7 @@
1
2
- 10550263
+ 10550244
2
@@ -14571,11 +14865,11 @@
type_mention
- 4147997
+ 4147990
id
- 4147997
+ 4147990
type_id
@@ -14583,7 +14877,7 @@
parent
- 1453787
+ 1453785
@@ -14597,7 +14891,7 @@
1
2
- 4147997
+ 4147990
@@ -14613,7 +14907,7 @@
1
2
- 4147997
+ 4147990
@@ -14670,7 +14964,7 @@
1
2
- 69690
+ 69689
2
@@ -14711,12 +15005,12 @@
1
2
- 1183982
+ 1183979
2
3
- 142436
+ 142435
3
@@ -14742,7 +15036,7 @@
1
2
- 1271409
+ 1271407
2
@@ -14762,15 +15056,15 @@
type_mention_location
- 4147997
+ 4147990
id
- 4147997
+ 4147990
loc
- 3077665
+ 3077659
@@ -14784,7 +15078,7 @@
1
2
- 4147997
+ 4147990
@@ -14800,12 +15094,12 @@
1
2
- 2705130
+ 2705125
2
3
- 359178
+ 359177
3
@@ -14820,11 +15114,11 @@
type_annotation
- 1491207
+ 1491205
id
- 1491207
+ 1491205
annotation
@@ -14842,7 +15136,7 @@
1
2
- 1491207
+ 1491205
@@ -15207,11 +15501,11 @@
type_nullability
- 32568461
+ 32568402
id
- 32566139
+ 32566081
nullability
@@ -15229,7 +15523,7 @@
1
2
- 32563905
+ 32563846
2
@@ -15300,11 +15594,11 @@
expr_flowstate
- 3848490
+ 3848496
id
- 3848490
+ 3848496
state
@@ -15322,7 +15616,7 @@
1
2
- 3848490
+ 3848496
@@ -15336,13 +15630,13 @@
12
- 210405
- 210406
+ 210406
+ 210407
1
- 2276574
- 2276575
+ 2276592
+ 2276593
1
@@ -15353,11 +15647,11 @@
type_parameters
- 830424
+ 830422
id
- 830424
+ 830422
index
@@ -15365,7 +15659,7 @@
generic_id
- 796402
+ 796400
variance
@@ -15383,7 +15677,7 @@
1
2
- 830424
+ 830422
@@ -15399,7 +15693,7 @@
1
2
- 830424
+ 830422
@@ -15415,7 +15709,7 @@
1
2
- 830424
+ 830422
@@ -15639,7 +15933,7 @@
1
2
- 789862
+ 789861
2
@@ -15660,7 +15954,7 @@
1
2
- 789862
+ 789861
2
@@ -15681,7 +15975,7 @@
1
2
- 796038
+ 796037
2
@@ -15774,11 +16068,11 @@
type_arguments
- 32946682
+ 32946623
id
- 851709
+ 851708
index
@@ -15786,7 +16080,7 @@
constructed_id
- 3572654
+ 3572648
@@ -15805,7 +16099,7 @@
2
3
- 720386
+ 720385
3
@@ -15831,7 +16125,7 @@
2
3
- 721262
+ 721261
3
@@ -16044,7 +16338,7 @@
2
3
- 2211295
+ 2211291
3
@@ -16054,17 +16348,17 @@
20
25
- 281239
+ 281238
25
29
- 321416
+ 321415
29
32
- 283718
+ 283717
32
@@ -16090,27 +16384,27 @@
2
3
- 2211338
+ 2211334
3
20
- 305986
+ 305985
20
25
- 281239
+ 281238
25
29
- 321416
+ 321415
29
32
- 283718
+ 283717
32
@@ -16125,11 +16419,11 @@
constructed_generic
- 3862925
+ 3862918
constructed
- 3862925
+ 3862918
generic
@@ -16147,7 +16441,7 @@
1
2
- 3862925
+ 3862918
@@ -16213,15 +16507,15 @@
type_parameter_constraints
- 1730282
+ 1730279
id
- 1730282
+ 1730279
param_id
- 831792
+ 831790
@@ -16235,7 +16529,7 @@
1
2
- 1730282
+ 1730279
@@ -16256,7 +16550,7 @@
2
3
- 777766
+ 777765
3
@@ -16384,7 +16678,7 @@
id
- 254828
+ 254827
base_id
@@ -16402,7 +16696,7 @@
1
2
- 250207
+ 250206
2
@@ -16463,11 +16757,11 @@
specific_type_parameter_nullability
- 48893
+ 48843
id
- 48656
+ 48606
base_id
@@ -16489,7 +16783,7 @@
1
2
- 48418
+ 48369
2
@@ -16510,7 +16804,7 @@
1
2
- 48656
+ 48606
@@ -16686,8 +16980,8 @@
1
- 35929
- 35930
+ 35892
+ 35893
1
@@ -16935,11 +17229,11 @@
has_modifiers
- 74006635
+ 74006502
id
- 48974345
+ 48974257
mod_id
@@ -16957,17 +17251,17 @@
1
2
- 25150157
+ 25150112
2
3
- 22619211
+ 22619170
3
5
- 1204976
+ 1204974
@@ -17058,11 +17352,11 @@
compiler_generated
- 786251
+ 786249
id
- 786251
+ 786249
@@ -17157,19 +17451,19 @@
nested_types
- 1588195
+ 1588192
id
- 1588195
+ 1588192
declaring_type_id
- 637373
+ 637372
unbound_id
- 1331870
+ 1331867
@@ -17183,7 +17477,7 @@
1
2
- 1588195
+ 1588192
@@ -17199,7 +17493,7 @@
1
2
- 1588195
+ 1588192
@@ -17215,7 +17509,7 @@
1
2
- 373000
+ 372999
2
@@ -17235,7 +17529,7 @@
6
22
- 47989
+ 47988
22
@@ -17256,7 +17550,7 @@
1
2
- 374540
+ 374539
2
@@ -17297,7 +17591,7 @@
1
2
- 1283295
+ 1283293
2
@@ -17318,7 +17612,7 @@
1
2
- 1291083
+ 1291081
2
@@ -17333,27 +17627,27 @@
properties
- 4879894
+ 4879885
id
- 4879894
+ 4879885
name
- 1131843
+ 1131841
declaring_type_id
- 1362395
+ 1362392
type_id
- 541612
+ 541611
unbound_id
- 4365920
+ 4365913
@@ -17367,7 +17661,7 @@
1
2
- 4879894
+ 4879885
@@ -17383,7 +17677,7 @@
1
2
- 4879894
+ 4879885
@@ -17399,7 +17693,7 @@
1
2
- 4879894
+ 4879885
@@ -17415,7 +17709,7 @@
1
2
- 4879894
+ 4879885
@@ -17431,7 +17725,7 @@
1
2
- 714282
+ 714280
2
@@ -17467,7 +17761,7 @@
1
2
- 714282
+ 714280
2
@@ -17503,7 +17797,7 @@
1
2
- 989546
+ 989545
2
@@ -17529,12 +17823,12 @@
1
2
- 720508
+ 720507
2
3
- 186641
+ 186640
3
@@ -17565,12 +17859,12 @@
1
2
- 484967
+ 484966
2
3
- 319782
+ 319781
3
@@ -17585,7 +17879,7 @@
5
7
- 114614
+ 114613
7
@@ -17611,12 +17905,12 @@
1
2
- 560096
+ 560095
2
3
- 245846
+ 245845
3
@@ -17657,7 +17951,7 @@
1
2
- 562005
+ 562004
2
@@ -17667,7 +17961,7 @@
3
4
- 167788
+ 167787
4
@@ -17698,12 +17992,12 @@
1
2
- 484967
+ 484966
2
3
- 319782
+ 319781
3
@@ -17718,7 +18012,7 @@
5
7
- 114614
+ 114613
7
@@ -17790,7 +18084,7 @@
2
3
- 60572
+ 60571
3
@@ -17816,7 +18110,7 @@
1
2
- 309846
+ 309845
2
@@ -17857,12 +18151,12 @@
1
2
- 297480
+ 297479
2
3
- 113334
+ 113333
3
@@ -17898,7 +18192,7 @@
1
2
- 4291398
+ 4291391
2
@@ -17919,7 +18213,7 @@
1
2
- 4365920
+ 4365913
@@ -17935,7 +18229,7 @@
1
2
- 4291398
+ 4291391
2
@@ -17956,7 +18250,7 @@
1
2
- 4349931
+ 4349923
2
@@ -17971,15 +18265,15 @@
property_location
- 4890676
+ 4890667
id
- 4879894
+ 4879885
loc
- 8048
+ 8027
@@ -17993,7 +18287,7 @@
1
2
- 4872127
+ 4872118
2
@@ -18014,67 +18308,72 @@
1
5
- 694
+ 650
5
- 11
- 737
-
-
- 11
- 22
+ 10
607
- 22
- 37
- 607
-
-
- 37
- 53
+ 10
+ 18
629
- 53
- 96
+ 18
+ 34
607
- 96
- 139
+ 34
+ 49
607
- 141
- 214
+ 49
+ 81
607
- 214
- 291
+ 82
+ 126
607
- 292
- 393
+ 127
+ 187
607
- 409
- 912
+ 188
+ 272
607
- 921
- 2270
+ 272
+ 359
607
- 2333
+ 369
+ 750
+ 607
+
+
+ 759
+ 1795
+ 607
+
+
+ 1886
+ 9614
+ 607
+
+
+ 9940
12699
- 520
+ 65
@@ -18333,7 +18632,7 @@
1
2
- 72463
+ 72462
2
@@ -18695,11 +18994,11 @@
accessors
- 5815073
+ 5815063
id
- 5815073
+ 5815063
kind
@@ -18707,15 +19006,15 @@
name
- 1544393
+ 1544390
declaring_member_id
- 4956672
+ 4956663
unbound_id
- 5171668
+ 5171659
@@ -18729,7 +19028,7 @@
1
2
- 5815073
+ 5815063
@@ -18745,7 +19044,7 @@
1
2
- 5815073
+ 5815063
@@ -18761,7 +19060,7 @@
1
2
- 5815073
+ 5815063
@@ -18777,7 +19076,7 @@
1
2
- 5815073
+ 5815063
@@ -18877,7 +19176,7 @@
1
2
- 1004407
+ 1004406
2
@@ -18913,7 +19212,7 @@
1
2
- 1544393
+ 1544390
@@ -18929,7 +19228,7 @@
1
2
- 1004407
+ 1004406
2
@@ -18965,12 +19264,12 @@
1
2
- 1015298
+ 1015296
2
3
- 249556
+ 249555
3
@@ -19001,12 +19300,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19022,12 +19321,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19043,12 +19342,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19064,12 +19363,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19085,12 +19384,12 @@
1
2
- 5083717
+ 5083708
2
1206
- 87951
+ 87950
@@ -19106,7 +19405,7 @@
1
2
- 5171668
+ 5171659
@@ -19122,7 +19421,7 @@
1
2
- 5171668
+ 5171659
@@ -19138,12 +19437,12 @@
1
2
- 5083717
+ 5083708
2
1206
- 87951
+ 87950
@@ -19164,15 +19463,15 @@
accessor_location
- 5828090
+ 5828080
id
- 5815073
+ 5815063
loc
- 8048
+ 8027
@@ -19186,7 +19485,7 @@
1
2
- 5805202
+ 5805192
2
@@ -19207,67 +19506,67 @@
1
6
- 694
+ 650
6
- 13
- 715
-
-
- 13
- 26
- 629
-
-
- 26
- 43
+ 12
607
- 44
- 68
+ 12
+ 22
607
- 68
- 106
+ 22
+ 38
+ 650
+
+
+ 38
+ 66
+ 672
+
+
+ 67
+ 105
607
- 116
- 167
+ 105
+ 161
607
- 168
- 273
- 629
-
-
- 275
- 373
+ 164
+ 269
607
- 373
- 492
+ 269
+ 361
607
- 517
- 1154
+ 364
+ 464
607
- 1167
- 2661
+ 477
+ 1105
607
- 2853
+ 1105
+ 2387
+ 607
+
+
+ 2455
13984
- 520
+ 585
@@ -19802,7 +20101,7 @@
1
2
- 50050
+ 50049
2
@@ -19839,7 +20138,7 @@
1
2
- 50050
+ 50049
2
@@ -19860,7 +20159,7 @@
1
2
- 51547
+ 51546
2
@@ -20318,7 +20617,7 @@
1
2
- 100100
+ 100099
2
@@ -20371,7 +20670,7 @@
1
2
- 100100
+ 100099
2
@@ -20479,11 +20778,11 @@
operators
- 807643
+ 807641
id
- 807643
+ 807641
name
@@ -20495,7 +20794,7 @@
declaring_type_id
- 94480
+ 94479
type_id
@@ -20517,7 +20816,7 @@
1
2
- 807643
+ 807641
@@ -20533,7 +20832,7 @@
1
2
- 807643
+ 807641
@@ -20549,7 +20848,7 @@
1
2
- 807643
+ 807641
@@ -20565,7 +20864,7 @@
1
2
- 807643
+ 807641
@@ -20581,7 +20880,7 @@
1
2
- 807643
+ 807641
@@ -21148,7 +21447,7 @@
1
2
- 92172
+ 92171
2
@@ -21169,7 +21468,7 @@
1
2
- 92172
+ 92171
2
@@ -21606,11 +21905,11 @@
operator_location
- 1510292
+ 1510289
id
- 751074
+ 751073
loc
@@ -21633,7 +21932,7 @@
2
3
- 740026
+ 740024
3
@@ -21672,9 +21971,9 @@
1880
- 63
+ 62
73
- 1859
+ 1880
75
@@ -21688,8 +21987,8 @@
96
- 20093
- 897
+ 18513
+ 876
@@ -21699,15 +21998,15 @@
constant_value
- 2847105
+ 2847100
id
- 2845825
+ 2845820
value
- 965573
+ 965572
@@ -21721,7 +22020,7 @@
1
2
- 2844979
+ 2844974
2
@@ -21742,7 +22041,7 @@
1
2
- 780581
+ 780580
2
@@ -21767,27 +22066,27 @@
methods
- 15027131
+ 15027104
id
- 15027131
+ 15027104
name
- 4232388
+ 4232381
declaring_type_id
- 3140811
+ 3140805
type_id
- 999548
+ 999546
unbound_id
- 12416413
+ 12416391
@@ -21801,7 +22100,7 @@
1
2
- 15027131
+ 15027104
@@ -21817,7 +22116,7 @@
1
2
- 15027131
+ 15027104
@@ -21833,7 +22132,7 @@
1
2
- 15027131
+ 15027104
@@ -21849,7 +22148,7 @@
1
2
- 15027131
+ 15027104
@@ -21865,22 +22164,22 @@
1
2
- 3032748
+ 3032743
2
3
- 495706
+ 495705
3
5
- 336878
+ 336877
5
26
- 319392
+ 319391
26
@@ -21901,17 +22200,17 @@
1
2
- 3164935
+ 3164930
2
3
- 431663
+ 431662
3
6
- 378510
+ 378509
6
@@ -21932,12 +22231,12 @@
1
2
- 3856394
+ 3856388
2
7
- 323514
+ 323513
7
@@ -21958,22 +22257,22 @@
1
2
- 3079284
+ 3079278
2
3
- 510241
+ 510240
3
5
- 336444
+ 336443
5
8458
- 306418
+ 306417
@@ -21989,12 +22288,12 @@
1
2
- 1095786
+ 1095784
2
3
- 701525
+ 701524
3
@@ -22014,12 +22313,12 @@
6
9
- 274635
+ 274634
9
18
- 241659
+ 241658
18
@@ -22040,17 +22339,17 @@
1
2
- 1137440
+ 1137438
2
3
- 725802
+ 725800
3
4
- 320845
+ 320844
4
@@ -22065,12 +22364,12 @@
6
10
- 265567
+ 265566
10
70
- 235693
+ 235692
70
@@ -22091,12 +22390,12 @@
1
2
- 1500895
+ 1500892
2
3
- 768953
+ 768951
3
@@ -22106,7 +22405,7 @@
4
5
- 257670
+ 257669
5
@@ -22116,7 +22415,7 @@
10
848
- 62351
+ 62350
@@ -22132,12 +22431,12 @@
1
2
- 1095808
+ 1095806
2
3
- 701503
+ 701502
3
@@ -22157,12 +22456,12 @@
6
9
- 274635
+ 274634
9
18
- 241659
+ 241658
18
@@ -22183,7 +22482,7 @@
1
2
- 566843
+ 566842
2
@@ -22224,7 +22523,7 @@
1
2
- 697078
+ 697076
2
@@ -22260,7 +22559,7 @@
1
2
- 648915
+ 648914
2
@@ -22296,7 +22595,7 @@
1
2
- 568861
+ 568860
2
@@ -22337,12 +22636,12 @@
1
2
- 12025102
+ 12025081
2
3017
- 391310
+ 391309
@@ -22358,7 +22657,7 @@
1
2
- 12416413
+ 12416391
@@ -22374,7 +22673,7 @@
1
2
- 12025189
+ 12025167
2
@@ -22395,12 +22694,12 @@
1
2
- 12291928
+ 12291906
2
1636
- 124485
+ 124484
@@ -22410,15 +22709,15 @@
method_location
- 15099549
+ 15099522
id
- 15027131
+ 15027104
loc
- 8526
+ 8504
@@ -22432,7 +22731,7 @@
1
2
- 14977211
+ 14977184
2
@@ -22458,7 +22757,7 @@
6
22
- 672
+ 650
23
@@ -22523,23 +22822,23 @@
constructors
- 4401500
+ 4401492
id
- 4401500
+ 4401492
name
- 2051728
+ 2051724
declaring_type_id
- 3294779
+ 3294773
unbound_id
- 4086621
+ 4086613
@@ -22553,7 +22852,7 @@
1
2
- 4401500
+ 4401492
@@ -22569,7 +22868,7 @@
1
2
- 4401500
+ 4401492
@@ -22585,7 +22884,7 @@
1
2
- 4401500
+ 4401492
@@ -22601,17 +22900,17 @@
1
2
- 1486728
+ 1486725
2
3
- 373000
+ 372999
3
7
- 156767
+ 156766
7
@@ -22632,7 +22931,7 @@
1
2
- 1877995
+ 1877992
2
@@ -22658,12 +22957,12 @@
1
2
- 1508922
+ 1508919
2
3
- 374193
+ 374192
3
@@ -22689,17 +22988,17 @@
1
2
- 2455035
+ 2455031
2
3
- 711700
+ 711699
3
55
- 128043
+ 128042
@@ -22715,7 +23014,7 @@
1
2
- 3294779
+ 3294773
@@ -22731,17 +23030,17 @@
1
2
- 2455035
+ 2455031
2
3
- 711700
+ 711699
3
55
- 128043
+ 128042
@@ -22757,7 +23056,7 @@
1
2
- 4045053
+ 4045046
2
@@ -22778,7 +23077,7 @@
1
2
- 4086621
+ 4086613
@@ -22794,7 +23093,7 @@
1
2
- 4045053
+ 4045046
2
@@ -22809,11 +23108,11 @@
constructor_location
- 4437817
+ 4437809
id
- 4401500
+ 4401492
loc
@@ -22831,7 +23130,7 @@
1
2
- 4386878
+ 4386870
2
@@ -23226,15 +23525,15 @@
overrides
- 3549976
+ 3549970
id
- 3549976
+ 3549970
base_id
- 1153191
+ 1153189
@@ -23248,7 +23547,7 @@
1
2
- 3549976
+ 3549970
@@ -23264,12 +23563,12 @@
1
2
- 787090
+ 787088
2
3
- 181586
+ 181585
3
@@ -23294,11 +23593,11 @@
explicitly_implements
- 1340287
+ 1340285
id
- 1339875
+ 1339873
interface_id
@@ -23316,7 +23615,7 @@
1
2
- 1339463
+ 1339461
2
@@ -23668,15 +23967,15 @@
local_function_stmts
- 3317
+ 3316
fn
- 3317
+ 3316
stmt
- 3317
+ 3316
@@ -23690,7 +23989,7 @@
1
2
- 3317
+ 3316
@@ -23706,7 +24005,7 @@
1
2
- 3317
+ 3316
@@ -23716,11 +24015,11 @@
fields
- 11002601
+ 11002581
id
- 11002601
+ 11002581
kind
@@ -23728,19 +24027,19 @@
name
- 4569136
+ 4569128
declaring_type_id
- 2488012
+ 2488007
type_id
- 2180552
+ 2180548
unbound_id
- 10641880
+ 10641861
@@ -23754,7 +24053,7 @@
1
2
- 11002601
+ 11002581
@@ -23770,7 +24069,7 @@
1
2
- 11002601
+ 11002581
@@ -23786,7 +24085,7 @@
1
2
- 11002601
+ 11002581
@@ -23802,7 +24101,7 @@
1
2
- 11002601
+ 11002581
@@ -23818,7 +24117,7 @@
1
2
- 11002601
+ 11002581
@@ -23939,17 +24238,17 @@
1
2
- 3598616
+ 3598609
2
3
- 510458
+ 510457
3
8
- 343495
+ 343494
8
@@ -23970,7 +24269,7 @@
1
2
- 4464307
+ 4464299
2
@@ -23991,17 +24290,17 @@
1
2
- 3598616
+ 3598609
2
3
- 510480
+ 510479
3
8
- 343473
+ 343472
8
@@ -24022,7 +24321,7 @@
1
2
- 4006545
+ 4006538
2
@@ -24048,17 +24347,17 @@
1
2
- 3622827
+ 3622821
2
3
- 511717
+ 511716
3
10
- 352368
+ 352367
10
@@ -24079,12 +24378,12 @@
1
2
- 686274
+ 686272
2
3
- 636267
+ 636266
3
@@ -24094,7 +24393,7 @@
4
5
- 217773
+ 217772
5
@@ -24104,17 +24403,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24130,7 +24429,7 @@
1
2
- 2338469
+ 2338465
2
@@ -24151,22 +24450,22 @@
1
2
- 686274
+ 686272
2
3
- 636289
+ 636287
3
4
- 353236
+ 353235
4
5
- 217773
+ 217772
5
@@ -24176,17 +24475,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24202,12 +24501,12 @@
1
2
- 948001
+ 947999
2
3
- 690981
+ 690980
3
@@ -24222,7 +24521,7 @@
5
8
- 228447
+ 228446
8
@@ -24243,12 +24542,12 @@
1
2
- 686274
+ 686272
2
3
- 636267
+ 636266
3
@@ -24258,7 +24557,7 @@
4
5
- 217773
+ 217772
5
@@ -24268,17 +24567,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24294,7 +24593,7 @@
1
2
- 1482497
+ 1482495
2
@@ -24330,7 +24629,7 @@
1
2
- 2117246
+ 2117242
2
@@ -24351,12 +24650,12 @@
1
2
- 1587652
+ 1587650
2
3
- 258950
+ 258949
3
@@ -24382,7 +24681,7 @@
1
2
- 1645773
+ 1645770
2
@@ -24413,17 +24712,17 @@
1
2
- 1486142
+ 1486139
2
3
- 270687
+ 270686
3
5
- 199354
+ 199353
5
@@ -24449,7 +24748,7 @@
1
2
- 10580071
+ 10580052
2
@@ -24470,7 +24769,7 @@
1
2
- 10641880
+ 10641861
@@ -24486,7 +24785,7 @@
1
2
- 10641880
+ 10641861
@@ -24502,7 +24801,7 @@
1
2
- 10580071
+ 10580052
2
@@ -24523,7 +24822,7 @@
1
2
- 10622637
+ 10622618
2
@@ -24538,15 +24837,15 @@
field_location
- 10994335
+ 10994315
id
- 10929771
+ 10929752
loc
- 8265
+ 8244
@@ -24560,7 +24859,7 @@
1
2
- 10890872
+ 10890853
2
@@ -24581,7 +24880,7 @@
1
10
- 650
+ 629
10
@@ -24656,11 +24955,11 @@
localvars
- 354447
+ 354446
id
- 354447
+ 354446
kind
@@ -24680,7 +24979,7 @@
parent_id
- 354447
+ 354446
@@ -24694,7 +24993,7 @@
1
2
- 354447
+ 354446
@@ -24710,7 +25009,7 @@
1
2
- 354447
+ 354446
@@ -24726,7 +25025,7 @@
1
2
- 354447
+ 354446
@@ -24742,7 +25041,7 @@
1
2
- 354447
+ 354446
@@ -24758,7 +25057,7 @@
1
2
- 354447
+ 354446
@@ -25299,7 +25598,7 @@
1
2
- 354447
+ 354446
@@ -25315,7 +25614,7 @@
1
2
- 354447
+ 354446
@@ -25331,7 +25630,7 @@
1
2
- 354447
+ 354446
@@ -25347,7 +25646,7 @@
1
2
- 354447
+ 354446
@@ -25363,7 +25662,7 @@
1
2
- 354447
+ 354446
@@ -25373,15 +25672,15 @@
localvar_location
- 354447
+ 354446
id
- 354447
+ 354446
loc
- 354447
+ 354446
@@ -25395,7 +25694,7 @@
1
2
- 354447
+ 354446
@@ -25411,7 +25710,7 @@
1
2
- 354447
+ 354446
@@ -25421,19 +25720,19 @@
params
- 27466281
+ 27466231
id
- 27466281
+ 27466231
name
- 1613730
+ 1613727
type_id
- 2077566
+ 2077562
index
@@ -25445,11 +25744,11 @@
parent_id
- 15223817
+ 15223790
unbound_id
- 22123570
+ 22123530
@@ -25463,7 +25762,7 @@
1
2
- 27466281
+ 27466231
@@ -25479,7 +25778,7 @@
1
2
- 27466281
+ 27466231
@@ -25495,7 +25794,7 @@
1
2
- 27466281
+ 27466231
@@ -25511,7 +25810,7 @@
1
2
- 27466281
+ 27466231
@@ -25527,7 +25826,7 @@
1
2
- 27466281
+ 27466231
@@ -25543,7 +25842,7 @@
1
2
- 27466281
+ 27466231
@@ -25559,7 +25858,7 @@
1
2
- 721137
+ 721136
2
@@ -25605,12 +25904,12 @@
1
2
- 1310934
+ 1310932
2
3
- 157331
+ 157330
3
@@ -25636,7 +25935,7 @@
1
2
- 1115941
+ 1115939
2
@@ -25651,7 +25950,7 @@
4
21
- 115113
+ 115112
@@ -25667,7 +25966,7 @@
1
2
- 1492260
+ 1492257
2
@@ -25693,7 +25992,7 @@
1
2
- 721137
+ 721136
2
@@ -25739,7 +26038,7 @@
1
2
- 736237
+ 736236
2
@@ -25749,12 +26048,12 @@
3
4
- 146896
+ 146895
4
6
- 147742
+ 147741
6
@@ -25785,22 +26084,22 @@
1
2
- 1018379
+ 1018377
2
3
- 301667
+ 301666
3
4
- 173277
+ 173276
4
5
- 129106
+ 129105
5
@@ -25810,7 +26109,7 @@
8
19
- 161171
+ 161170
19
@@ -25831,7 +26130,7 @@
1
2
- 1396976
+ 1396974
2
@@ -25841,7 +26140,7 @@
3
4
- 149456
+ 149455
4
@@ -25867,7 +26166,7 @@
1
2
- 1515539
+ 1515536
2
@@ -25898,7 +26197,7 @@
1
2
- 1956596
+ 1956592
2
@@ -25919,17 +26218,17 @@
1
2
- 1049359
+ 1049357
2
3
- 281903
+ 281902
3
4
- 174123
+ 174122
4
@@ -25939,17 +26238,17 @@
5
9
- 182085
+ 182084
9
24
- 157483
+ 157482
24
74138
- 105220
+ 105219
@@ -25965,12 +26264,12 @@
1
2
- 1024605
+ 1024603
2
3
- 302795
+ 302794
3
@@ -26603,22 +26902,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26639,22 +26938,22 @@
1
2
- 8608246
+ 8608230
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153863
+ 1153861
8
@@ -26675,22 +26974,22 @@
1
2
- 9102195
+ 9102178
2
3
- 3783500
+ 3783493
3
4
- 1384350
+ 1384347
4
43
- 953771
+ 953770
@@ -26706,22 +27005,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26742,12 +27041,12 @@
1
2
- 14543531
+ 14543505
2
5
- 680286
+ 680285
@@ -26763,22 +27062,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26799,12 +27098,12 @@
1
2
- 21382863
+ 21382825
2
17584
- 740706
+ 740705
@@ -26820,7 +27119,7 @@
1
2
- 22123505
+ 22123465
2
@@ -26841,12 +27140,12 @@
1
2
- 21899331
+ 21899292
2
9835
- 224238
+ 224237
@@ -26862,7 +27161,7 @@
1
2
- 22123570
+ 22123530
@@ -26878,7 +27177,7 @@
1
2
- 22123570
+ 22123530
@@ -26894,12 +27193,12 @@
1
2
- 21382863
+ 21382825
2
17584
- 740706
+ 740705
@@ -26909,11 +27208,11 @@
param_location
- 27592957
+ 27592908
id
- 27465934
+ 27465884
loc
@@ -26931,7 +27230,7 @@
1
2
- 27379957
+ 27379908
2
@@ -27376,11 +27675,11 @@
stmt_parent_top_level
- 249938
+ 249937
stmt
- 249938
+ 249937
index
@@ -27388,7 +27687,7 @@
parent
- 171227
+ 171226
@@ -27402,7 +27701,7 @@
1
2
- 249938
+ 249937
@@ -27418,7 +27717,7 @@
1
2
- 249938
+ 249937
@@ -27466,7 +27765,7 @@
1
2
- 106304
+ 106303
2
@@ -27497,7 +27796,7 @@
1
2
- 171227
+ 171226
@@ -27965,11 +28264,11 @@
expressions
- 6684214
+ 6684202
id
- 6684214
+ 6684202
kind
@@ -27991,7 +28290,7 @@
1
2
- 6684214
+ 6684202
@@ -28007,7 +28306,7 @@
1
2
- 6684214
+ 6684202
@@ -28256,11 +28555,11 @@
expr_parent
- 6472330
+ 6472322
expr
- 6472330
+ 6472322
index
@@ -28268,7 +28567,7 @@
parent
- 4333969
+ 4333965
@@ -28282,7 +28581,7 @@
1
2
- 6472330
+ 6472322
@@ -28298,7 +28597,7 @@
1
2
- 6472330
+ 6472322
@@ -28343,7 +28642,7 @@
66
- 3205676
+ 3205672
489
@@ -28389,7 +28688,7 @@
66
- 3205676
+ 3205672
489
@@ -28411,7 +28710,7 @@
2
3
- 1302939
+ 1302935
3
@@ -28437,7 +28736,7 @@
2
3
- 1302939
+ 1302935
3
@@ -28452,11 +28751,11 @@
expr_parent_top_level
- 4527928
+ 4527920
expr
- 4527928
+ 4527920
index
@@ -28464,7 +28763,7 @@
parent
- 4069954
+ 4069947
@@ -28478,7 +28777,7 @@
1
2
- 4527928
+ 4527920
@@ -28494,7 +28793,7 @@
1
2
- 4527928
+ 4527920
@@ -28562,7 +28861,7 @@
1
2
- 3716443
+ 3716436
2
@@ -28588,7 +28887,7 @@
1
2
- 3726770
+ 3726764
2
@@ -28603,11 +28902,11 @@
implicitly_typed_array_creation
- 19612
+ 19611
id
- 19612
+ 19611
@@ -28695,26 +28994,26 @@
expr_compiler_generated
- 6677184
+ 6677172
id
- 6677184
+ 6677172
expr_value
- 5479091
+ 5479081
id
- 5479091
+ 5479081
value
- 203506
+ 203505
@@ -28728,7 +29027,7 @@
1
2
- 5479091
+ 5479081
@@ -28779,15 +29078,15 @@
expr_call
- 1125746
+ 1125744
caller_id
- 1125746
+ 1125744
target_id
- 895583
+ 895582
@@ -28801,7 +29100,7 @@
1
2
- 1125746
+ 1125744
@@ -28817,7 +29116,7 @@
1
2
- 893788
+ 893787
2
@@ -28910,15 +29209,15 @@
expr_location
- 6684214
+ 6684202
id
- 6684214
+ 6684202
loc
- 5325109
+ 5325100
@@ -28932,7 +29231,7 @@
1
2
- 6684214
+ 6684202
@@ -28948,12 +29247,12 @@
1
2
- 4609547
+ 4609539
2
3
- 691472
+ 691471
3
@@ -29057,11 +29356,11 @@
expr_argument
- 1381112
+ 1381083
id
- 1381112
+ 1381083
mode
@@ -29079,7 +29378,7 @@
1
2
- 1381112
+ 1381083
@@ -29120,11 +29419,11 @@
expr_argument_name
- 537620
+ 537619
id
- 537620
+ 537619
name
@@ -29142,7 +29441,7 @@
1
2
- 537620
+ 537619
@@ -29223,11 +29522,11 @@
xmlEncoding
- 476428
+ 476427
id
- 476428
+ 476427
encoding
@@ -29245,7 +29544,7 @@
1
2
- 476428
+ 476427
@@ -29739,11 +30038,11 @@
xmlElements
- 1042734675
+ 1042732803
id
- 1042734675
+ 1042732803
name
@@ -29751,15 +30050,15 @@
parentid
- 385731802
+ 385731109
idx
- 1630081
+ 1630078
fileid
- 476089
+ 476088
@@ -29773,7 +30072,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29789,7 +30088,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29805,7 +30104,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29821,7 +30120,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29919,7 +30218,7 @@
1
2
- 180311
+ 180310
2
@@ -29950,7 +30249,7 @@
1
2
- 171338
+ 171337
2
@@ -29991,32 +30290,32 @@
1
2
- 187348969
+ 187348633
2
3
- 87399822
+ 87399665
3
4
- 39675923
+ 39675851
4
5
- 25725419
+ 25725373
5
8
- 33529933
+ 33529873
8
9629
- 12051732
+ 12051711
@@ -30032,27 +30331,27 @@
1
2
- 244194247
+ 244193809
2
3
- 69983618
+ 69983493
3
4
- 32247777
+ 32247719
4
5
- 25493131
+ 25493085
5
110
- 13813026
+ 13813001
@@ -30068,32 +30367,32 @@
1
2
- 187348969
+ 187348633
2
3
- 87399822
+ 87399665
3
4
- 39675923
+ 39675851
4
5
- 25725419
+ 25725373
5
8
- 33529933
+ 33529873
8
9629
- 12051732
+ 12051711
@@ -30109,7 +30408,7 @@
1
2
- 385731802
+ 385731109
@@ -30130,12 +30429,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30160,7 +30459,7 @@
141
322
- 123255
+ 123254
322
@@ -30181,7 +30480,7 @@
1
2
- 1566422
+ 1566419
2
@@ -30207,12 +30506,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30237,7 +30536,7 @@
141
322
- 123255
+ 123254
322
@@ -30263,12 +30562,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30293,7 +30592,7 @@
141
322
- 123255
+ 123254
322
@@ -30405,12 +30704,12 @@
7
9
- 24888
+ 24887
9
11
- 43681
+ 43680
11
@@ -30557,7 +30856,7 @@
51
101
- 39279
+ 39278
102
@@ -30602,15 +30901,15 @@
xmlAttrs
- 782957811
+ 782956405
id
- 782957811
+ 782956405
elementid
- 772812975
+ 772811588
name
@@ -30618,7 +30917,7 @@
value
- 16557651
+ 16557621
idx
@@ -30626,7 +30925,7 @@
fileid
- 469994
+ 469993
@@ -30640,7 +30939,7 @@
1
2
- 782957811
+ 782956405
@@ -30656,7 +30955,7 @@
1
2
- 782957811
+ 782956405
@@ -30672,7 +30971,7 @@
1
2
- 782957811
+ 782956405
@@ -30688,7 +30987,7 @@
1
2
- 782957811
+ 782956405
@@ -30704,7 +31003,7 @@
1
2
- 782957811
+ 782956405
@@ -30720,12 +31019,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30741,12 +31040,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30762,12 +31061,12 @@
1
2
- 767717701
+ 767716323
2
13
- 5095274
+ 5095264
@@ -30783,12 +31082,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30804,7 +31103,7 @@
1
2
- 772812975
+ 772811588
@@ -31105,42 +31404,42 @@
1
2
- 4011882
+ 4011875
2
3
- 1419294
+ 1419292
3
4
- 5374629
+ 5374619
4
6
- 795909
+ 795907
6
8
- 1488541
+ 1488538
8
27
- 1245586
+ 1245584
27
90
- 1243047
+ 1243044
90
214809
- 978759
+ 978758
@@ -31156,42 +31455,42 @@
1
2
- 4012898
+ 4012891
2
3
- 1419125
+ 1419123
3
4
- 5374968
+ 5374958
4
6
- 797094
+ 797092
6
8
- 1488033
+ 1488030
8
27
- 1244062
+ 1244060
27
90
- 1242877
+ 1242875
90
214809
- 978590
+ 978588
@@ -31207,12 +31506,12 @@
1
2
- 14765543
+ 14765517
2
3
- 1766203
+ 1766200
3
@@ -31233,7 +31532,7 @@
1
2
- 16464702
+ 16464672
2
@@ -31254,37 +31553,37 @@
1
2
- 4652030
+ 4652021
2
3
- 1284019
+ 1284016
3
4
- 6041188
+ 6041177
4
6
- 779994
+ 779992
6
8
- 1312293
+ 1312291
8
44
- 1256930
+ 1256927
44
1527
- 1231195
+ 1231193
@@ -31685,7 +31984,7 @@
711
1058
- 35385
+ 35384
1065
@@ -31741,7 +32040,7 @@
12
44
- 35385
+ 35384
44
@@ -31807,7 +32106,7 @@
2
3
- 196226
+ 196225
3
@@ -31817,12 +32116,12 @@
4
5
- 24888
+ 24887
5
6
- 45882
+ 45881
6
@@ -31858,7 +32157,7 @@
4
7
- 35385
+ 35384
7
@@ -31883,7 +32182,7 @@
131
209
- 35385
+ 35384
210
@@ -31929,12 +32228,12 @@
1
2
- 300857
+ 300856
2
3
- 35385
+ 35384
3
@@ -31959,7 +32258,7 @@
xmlNs
- 27089
+ 27088
id
@@ -32345,11 +32644,11 @@
xmlHasNs
- 513336
+ 513335
elementId
- 513336
+ 513335
nsId
@@ -32371,7 +32670,7 @@
1
2
- 513336
+ 513335
@@ -32387,7 +32686,7 @@
1
2
- 513336
+ 513335
@@ -32756,7 +33055,7 @@
1
2
- 133244
+ 133243
2
@@ -32818,7 +33117,7 @@
1
2
- 74664
+ 74663
2
@@ -32921,7 +33220,7 @@
2
3
- 8296
+ 8295
3
@@ -32992,19 +33291,19 @@
xmlChars
- 808544061
+ 808542609
id
- 808544061
+ 808542609
text
- 49726793
+ 49726704
parentid
- 487106000
+ 487105125
idx
@@ -33016,7 +33315,7 @@
fileid
- 448831
+ 448830
@@ -33030,7 +33329,7 @@
1
2
- 808544061
+ 808542609
@@ -33046,7 +33345,7 @@
1
2
- 808544061
+ 808542609
@@ -33062,7 +33361,7 @@
1
2
- 808544061
+ 808542609
@@ -33078,7 +33377,7 @@
1
2
- 808544061
+ 808542609
@@ -33094,7 +33393,7 @@
1
2
- 808544061
+ 808542609
@@ -33110,57 +33409,57 @@
1
2
- 6839129
+ 6839117
2
3
- 2738529
+ 2738525
3
4
- 10689155
+ 10689136
4
6
- 3529021
+ 3529014
6
7
- 4911407
+ 4911398
7
9
- 3937218
+ 3937211
9
10
- 893260
+ 893258
10
11
- 7086485
+ 7086473
11
20
- 3458928
+ 3458922
20
49
- 3805837
+ 3805830
49
250680
- 1837820
+ 1837816
@@ -33176,57 +33475,57 @@
1
2
- 6839975
+ 6839963
2
3
- 2739545
+ 2739540
3
4
- 10692880
+ 10692860
4
6
- 3530375
+ 3530369
6
7
- 4916317
+ 4916308
7
9
- 3942128
+ 3942121
9
10
- 893937
+ 893935
10
11
- 7101554
+ 7101541
11
20
- 3452833
+ 3452827
20
49
- 3788737
+ 3788730
49
249267
- 1828508
+ 1828505
@@ -33242,12 +33541,12 @@
1
2
- 48571955
+ 48571867
2
32
- 1154838
+ 1154836
@@ -33263,7 +33562,7 @@
1
2
- 49726793
+ 49726704
@@ -33279,47 +33578,47 @@
1
2
- 8926168
+ 8926152
2
3
- 2072309
+ 2072305
3
4
- 13690110
+ 13690085
4
5
- 3843761
+ 3843754
5
7
- 4406535
+ 4406528
7
9
- 4286497
+ 4286490
9
10
- 688060
+ 688059
10
11
- 9242432
+ 9242416
11
1537
- 2570916
+ 2570912
@@ -33335,22 +33634,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137381760
+ 137381514
3
4
- 41081842
+ 41081769
4
38
- 22989598
+ 22989557
@@ -33366,22 +33665,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137537861
+ 137537614
3
4
- 41794961
+ 41794886
4
28
- 22120380
+ 22120340
@@ -33397,22 +33696,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137381760
+ 137381514
3
4
- 41081842
+ 41081769
4
38
- 22989598
+ 22989557
@@ -33428,7 +33727,7 @@
1
2
- 487104984
+ 487104109
2
@@ -33449,7 +33748,7 @@
1
2
- 487106000
+ 487105125
@@ -33966,7 +34265,7 @@
7
37
- 35385
+ 35384
37
@@ -34082,7 +34381,7 @@
1453
1973
- 39279
+ 39278
1995
@@ -34174,7 +34473,7 @@
1
2
- 447815
+ 447814
2
@@ -34189,15 +34488,15 @@
xmllocations
- 46972752
+ 46972668
xmlElement
- 46970079
+ 46969994
location
- 39595243
+ 39595172
@@ -34211,7 +34510,7 @@
1
2
- 46969994
+ 46969909
29
@@ -34232,12 +34531,12 @@
1
2
- 32374506
+ 32374448
2
3
- 7172695
+ 7172682
3
@@ -34252,11 +34551,11 @@
commentline
- 1227120
+ 1227125
id
- 1227120
+ 1227125
kind
@@ -34264,11 +34563,11 @@
text
- 47656
+ 47658
rawtext
- 47745
+ 47747
@@ -34282,7 +34581,7 @@
1
2
- 1227120
+ 1227125
@@ -34298,7 +34597,7 @@
1
2
- 1227120
+ 1227125
@@ -34314,7 +34613,7 @@
1
2
- 1227120
+ 1227125
@@ -34333,8 +34632,8 @@
2
- 6150
- 6151
+ 6153
+ 6154
2
@@ -34359,8 +34658,8 @@
2
- 660
- 661
+ 661
+ 662
2
@@ -34385,8 +34684,8 @@
2
- 663
- 664
+ 664
+ 665
2
@@ -34418,7 +34717,7 @@
3
5
- 4088
+ 4091
5
@@ -34444,7 +34743,7 @@
1
2
- 47649
+ 47651
2
@@ -34465,7 +34764,7 @@
1
2
- 47593
+ 47595
2
@@ -34496,7 +34795,7 @@
3
5
- 4065
+ 4067
5
@@ -34522,7 +34821,7 @@
1
2
- 47745
+ 47747
@@ -34538,7 +34837,7 @@
1
2
- 47745
+ 47747
@@ -34548,15 +34847,15 @@
commentline_location
- 1227120
+ 1227125
id
- 1227120
+ 1227125
loc
- 1227120
+ 1227125
@@ -34570,7 +34869,7 @@
1
2
- 1227120
+ 1227125
@@ -34586,7 +34885,7 @@
1
2
- 1227120
+ 1227125
@@ -34596,26 +34895,26 @@
commentblock
- 412296
+ 412295
id
- 412296
+ 412295
commentblock_location
- 412296
+ 412295
id
- 412296
+ 412295
loc
- 412296
+ 412295
@@ -34629,7 +34928,7 @@
1
2
- 412296
+ 412295
@@ -34645,7 +34944,7 @@
1
2
- 412296
+ 412295
@@ -34655,15 +34954,15 @@
commentblock_binding
- 1601079
+ 1601076
id
- 412296
+ 412295
entity
- 415904
+ 415903
bindtype
@@ -34728,7 +35027,7 @@
2
3
- 379365
+ 379364
3
@@ -34759,7 +35058,7 @@
3
4
- 345375
+ 345374
4
@@ -34836,15 +35135,15 @@
commentblock_child
- 1631666
+ 1631670
id
- 412296
+ 412295
commentline
- 1227120
+ 1227125
index
@@ -34893,7 +35192,7 @@
4
5
- 393790
+ 393789
5
@@ -34914,7 +35213,7 @@
1
2
- 1227120
+ 1227125
@@ -34930,12 +35229,12 @@
1
2
- 822573
+ 822579
2
3
- 404546
+ 404545
@@ -34985,7 +35284,7 @@
110
- 177
+ 180
7
@@ -35051,7 +35350,7 @@
110
- 177
+ 180
7
@@ -36712,11 +37011,11 @@
cil_instruction
- 370458591
+ 370457925
id
- 370458591
+ 370457925
opcode
@@ -36724,11 +37023,11 @@
index
- 1246869
+ 1246867
impl
- 17616263
+ 17616232
@@ -36742,7 +37041,7 @@
1
2
- 370458591
+ 370457925
@@ -36758,7 +37057,7 @@
1
2
- 370458591
+ 370457925
@@ -36774,7 +37073,7 @@
1
2
- 370458591
+ 370457925
@@ -37028,7 +37327,7 @@
3
4
- 343039
+ 343038
4
@@ -37048,7 +37347,7 @@
15
16
- 106652
+ 106651
16
@@ -37079,7 +37378,7 @@
1
2
- 523931
+ 523930
2
@@ -37140,7 +37439,7 @@
3
4
- 343039
+ 343038
4
@@ -37160,7 +37459,7 @@
15
16
- 106652
+ 106651
16
@@ -37191,57 +37490,57 @@
1
3
- 1299002
+ 1299000
3
4
- 3887982
+ 3887975
4
5
- 1827121
+ 1827117
5
6
- 1190311
+ 1190309
6
8
- 1392724
+ 1392721
8
11
- 1390272
+ 1390270
11
16
- 1446289
+ 1446286
16
23
- 1331978
+ 1331976
23
35
- 1364217
+ 1364214
35
67
- 1341329
+ 1341326
67
57474
- 1145034
+ 1145031
@@ -37257,52 +37556,52 @@
1
3
- 1301671
+ 1301668
3
4
- 4029628
+ 4029621
4
5
- 2083923
+ 2083919
5
6
- 1825211
+ 1825208
6
7
- 1176166
+ 1176164
7
9
- 1560903
+ 1560900
9
12
- 1593163
+ 1593160
12
16
- 1494538
+ 1494535
16
24
- 1379837
+ 1379835
24
77
- 1171219
+ 1171217
@@ -37318,57 +37617,57 @@
1
3
- 1299002
+ 1299000
3
4
- 3887982
+ 3887975
4
5
- 1827121
+ 1827117
5
6
- 1190311
+ 1190309
6
8
- 1392724
+ 1392721
8
11
- 1390272
+ 1390270
11
16
- 1446289
+ 1446286
16
23
- 1331978
+ 1331976
23
35
- 1364217
+ 1364214
35
67
- 1341329
+ 1341326
67
57474
- 1145034
+ 1145031
@@ -37378,15 +37677,15 @@
cil_jump
- 28397577
+ 28397526
instruction
- 28397577
+ 28397526
target
- 21559112
+ 21559074
@@ -37400,7 +37699,7 @@
1
2
- 28397577
+ 28397526
@@ -37416,17 +37715,17 @@
1
2
- 17986226
+ 17986194
2
3
- 2350922
+ 2350917
3
473
- 1221964
+ 1221961
@@ -37436,15 +37735,15 @@
cil_access
- 150867340
+ 150867069
instruction
- 150867340
+ 150867069
target
- 35942622
+ 35942557
@@ -37458,7 +37757,7 @@
1
2
- 150867340
+ 150867069
@@ -37474,32 +37773,32 @@
1
2
- 14815628
+ 14815601
2
3
- 9023572
+ 9023556
3
4
- 4374403
+ 4374395
4
5
- 2253837
+ 2253833
5
8
- 3030514
+ 3030508
8
72956
- 2444665
+ 2444661
@@ -37509,15 +37808,15 @@
cil_value
- 14528539
+ 14528513
instruction
- 14528539
+ 14528513
value
- 3617230
+ 3617224
@@ -37531,7 +37830,7 @@
1
2
- 14528539
+ 14528513
@@ -37547,22 +37846,22 @@
1
2
- 2708887
+ 2708882
2
3
- 497181
+ 497180
3
7
- 273507
+ 273506
7
182148
- 137654
+ 137653
@@ -37572,7 +37871,7 @@
cil_switch
- 2990400
+ 2990395
instruction
@@ -37584,7 +37883,7 @@
target
- 1319005
+ 1319002
@@ -37792,7 +38091,7 @@
1
2
- 1301584
+ 1301581
2
@@ -37813,7 +38112,7 @@
1
2
- 1172673
+ 1172671
2
@@ -37875,11 +38174,11 @@
cil_type_location
- 3557547
+ 3557541
id
- 3557547
+ 3557541
loc
@@ -37897,7 +38196,7 @@
1
2
- 3557547
+ 3557541
@@ -37973,11 +38272,11 @@
cil_method_location
- 21566771
+ 21566732
id
- 21566771
+ 21566732
loc
@@ -37995,7 +38294,7 @@
1
2
- 21566771
+ 21566732
@@ -38086,15 +38385,15 @@
cil_type
- 9109571
+ 9109554
id
- 9109571
+ 9109554
name
- 2569541
+ 2569536
kind
@@ -38102,11 +38401,11 @@
parent
- 1843609
+ 1843605
sourceDecl
- 5094760
+ 5094751
@@ -38120,7 +38419,7 @@
1
2
- 9109571
+ 9109554
@@ -38136,7 +38435,7 @@
1
2
- 9109571
+ 9109554
@@ -38152,7 +38451,7 @@
1
2
- 9109571
+ 9109554
@@ -38168,7 +38467,7 @@
1
2
- 9109571
+ 9109554
@@ -38184,12 +38483,12 @@
1
2
- 2257721
+ 2257716
2
4
- 215148
+ 215147
4
@@ -38210,7 +38509,7 @@
1
2
- 2569541
+ 2569536
@@ -38226,7 +38525,7 @@
1
2
- 2374656
+ 2374652
2
@@ -38252,12 +38551,12 @@
1
2
- 2346604
+ 2346600
2
5
- 199788
+ 199787
5
@@ -38417,7 +38716,7 @@
1
2
- 1199271
+ 1199269
2
@@ -38453,7 +38752,7 @@
1
2
- 1205692
+ 1205690
2
@@ -38489,7 +38788,7 @@
1
2
- 1815145
+ 1815142
2
@@ -38510,7 +38809,7 @@
1
2
- 1205302
+ 1205300
2
@@ -38546,7 +38845,7 @@
1
2
- 4875229
+ 4875221
2
@@ -38567,7 +38866,7 @@
1
2
- 5094760
+ 5094751
@@ -38583,7 +38882,7 @@
1
2
- 5094760
+ 5094751
@@ -38599,7 +38898,7 @@
1
2
- 5022820
+ 5022811
2
@@ -38881,23 +39180,23 @@
cil_method
- 28926216
+ 28926164
id
- 28926216
+ 28926164
name
- 5796090
+ 5796080
parent
- 5584869
+ 5584859
return_type
- 2472804
+ 2472799
@@ -38911,7 +39210,7 @@
1
2
- 28926216
+ 28926164
@@ -38927,7 +39226,7 @@
1
2
- 28926216
+ 28926164
@@ -38943,7 +39242,7 @@
1
2
- 28926216
+ 28926164
@@ -38959,22 +39258,22 @@
1
2
- 3864986
+ 3864979
2
3
- 884652
+ 884650
3
5
- 510719
+ 510718
5
19
- 435546
+ 435545
19
@@ -38995,17 +39294,17 @@
1
2
- 4034878
+ 4034871
2
3
- 825143
+ 825141
3
5
- 474033
+ 474032
5
@@ -39031,7 +39330,7 @@
1
2
- 5227663
+ 5227653
2
@@ -39057,37 +39356,37 @@
1
2
- 1766158
+ 1766155
2
3
- 1281082
+ 1281080
3
4
- 640779
+ 640778
4
5
- 458716
+ 458715
5
7
- 476614
+ 476613
7
11
- 481235
+ 481234
11
39
- 420880
+ 420879
39
@@ -39108,17 +39407,17 @@
1
2
- 1806055
+ 1806052
2
3
- 1302170
+ 1302167
3
4
- 656703
+ 656702
4
@@ -39133,7 +39432,7 @@
7
11
- 440384
+ 440383
11
@@ -39154,17 +39453,17 @@
1
2
- 2382488
+ 2382483
2
3
- 1477464
+ 1477462
3
4
- 630605
+ 630603
4
@@ -39174,12 +39473,12 @@
5
7
- 451123
+ 451122
7
12757
- 307503
+ 307502
@@ -39195,7 +39494,7 @@
1
2
- 1493649
+ 1493646
2
@@ -39215,7 +39514,7 @@
8
508819
- 175251
+ 175250
@@ -39231,17 +39530,17 @@
1
2
- 1692439
+ 1692436
2
3
- 398621
+ 398620
3
5
- 201133
+ 201132
5
@@ -39262,12 +39561,12 @@
1
2
- 1616680
+ 1616677
2
3
- 413309
+ 413308
3
@@ -39292,15 +39591,15 @@
cil_method_source_declaration
- 25660941
+ 25660895
method
- 25660941
+ 25660895
source
- 22347808
+ 22347768
@@ -39314,7 +39613,7 @@
1
2
- 25660941
+ 25660895
@@ -39330,12 +39629,12 @@
1
2
- 21046744
+ 21046706
2
981
- 1301063
+ 1301061
@@ -39345,15 +39644,15 @@
cil_method_implementation
- 19889366
+ 19889330
id
- 19889366
+ 19889330
method
- 19872444
+ 19872408
location
@@ -39371,7 +39670,7 @@
1
2
- 19889366
+ 19889330
@@ -39387,7 +39686,7 @@
1
2
- 19889366
+ 19889330
@@ -39403,7 +39702,7 @@
1
2
- 19870318
+ 19870282
2
@@ -39424,7 +39723,7 @@
1
2
- 19872444
+ 19872408
@@ -39586,15 +39885,15 @@
cil_implements
- 1031396
+ 1031394
id
- 1030962
+ 1030960
decl
- 190676
+ 190675
@@ -39608,7 +39907,7 @@
1
2
- 1030528
+ 1030526
2
@@ -39659,23 +39958,23 @@
cil_field
- 11684992
+ 11684971
id
- 11684992
+ 11684971
parent
- 2707933
+ 2707928
name
- 4586883
+ 4586875
field_type
- 2250192
+ 2250188
@@ -39689,7 +39988,7 @@
1
2
- 11684992
+ 11684971
@@ -39705,7 +40004,7 @@
1
2
- 11684992
+ 11684971
@@ -39721,7 +40020,7 @@
1
2
- 11684992
+ 11684971
@@ -39737,12 +40036,12 @@
1
2
- 796245
+ 796244
2
3
- 671000
+ 670999
3
@@ -39752,7 +40051,7 @@
4
5
- 241095
+ 241094
5
@@ -39762,12 +40061,12 @@
6
8
- 192889
+ 192888
8
15
- 209963
+ 209962
15
@@ -39788,12 +40087,12 @@
1
2
- 796245
+ 796244
2
3
- 671000
+ 670999
3
@@ -39803,7 +40102,7 @@
4
5
- 241095
+ 241094
5
@@ -39813,12 +40112,12 @@
6
8
- 192889
+ 192888
8
15
- 209963
+ 209962
15
@@ -39839,12 +40138,12 @@
1
2
- 917302
+ 917301
2
3
- 895521
+ 895519
3
@@ -39859,7 +40158,7 @@
5
8
- 237971
+ 237970
8
@@ -39880,12 +40179,12 @@
1
2
- 3517998
+ 3517991
2
3
- 582507
+ 582506
3
@@ -39911,12 +40210,12 @@
1
2
- 3517998
+ 3517991
2
3
- 582507
+ 582506
3
@@ -39942,7 +40241,7 @@
1
2
- 4006631
+ 4006624
2
@@ -39968,12 +40267,12 @@
1
2
- 1354823
+ 1354821
2
3
- 434331
+ 434330
3
@@ -39988,7 +40287,7 @@
7
58308
- 155422
+ 155421
@@ -40004,22 +40303,22 @@
1
2
- 1515669
+ 1515666
2
3
- 436132
+ 436131
3
6
- 184992
+ 184991
6
22697
- 113399
+ 113398
@@ -40035,22 +40334,22 @@
1
2
- 1648572
+ 1648569
2
3
- 261770
+ 261769
3
5
- 174839
+ 174838
5
33056
- 165011
+ 165010
@@ -40060,15 +40359,15 @@
cil_parameter
- 55186717
+ 55186618
id
- 55186717
+ 55186618
parameterizable
- 27728463
+ 27728414
index
@@ -40076,7 +40375,7 @@
param_type
- 7131258
+ 7131245
@@ -40090,7 +40389,7 @@
1
2
- 55186717
+ 55186618
@@ -40106,7 +40405,7 @@
1
2
- 55186717
+ 55186618
@@ -40122,7 +40421,7 @@
1
2
- 55186717
+ 55186618
@@ -40138,22 +40437,22 @@
1
2
- 12120712
+ 12120690
2
3
- 8866306
+ 8866290
3
4
- 4255190
+ 4255182
4
7
- 2154041
+ 2154037
7
@@ -40174,22 +40473,22 @@
1
2
- 12120712
+ 12120690
2
3
- 8866306
+ 8866290
3
4
- 4255190
+ 4255182
4
7
- 2154041
+ 2154037
7
@@ -40210,22 +40509,22 @@
1
2
- 12478872
+ 12478850
2
3
- 9036481
+ 9036465
3
4
- 4177088
+ 4177081
4
43
- 2036021
+ 2036017
@@ -40424,42 +40723,42 @@
1
2
- 2005301
+ 2005297
2
3
- 2103427
+ 2103423
3
4
- 781427
+ 781426
4
5
- 480433
+ 480432
5
7
- 544237
+ 544236
7
11
- 540137
+ 540136
11
36
- 538857
+ 538856
36
108909
- 137437
+ 137436
@@ -40475,37 +40774,37 @@
1
2
- 2033873
+ 2033869
2
3
- 2102125
+ 2102121
3
4
- 775331
+ 775330
4
5
- 473924
+ 473923
5
7
- 543586
+ 543585
7
11
- 537707
+ 537706
11
37
- 535321
+ 535320
37
@@ -40526,17 +40825,17 @@
1
2
- 5015009
+ 5015000
2
3
- 1530486
+ 1530484
3
6
- 535646
+ 535645
6
@@ -40551,37 +40850,37 @@
cil_parameter_in
- 263267
+ 263266
id
- 263267
+ 263266
cil_parameter_out
- 502431
+ 502430
id
- 502431
+ 502430
cil_setter
- 789281
+ 789279
prop
- 789281
+ 789279
method
- 789281
+ 789279
@@ -40595,7 +40894,7 @@
1
2
- 789281
+ 789279
@@ -40611,7 +40910,7 @@
1
2
- 789281
+ 789279
@@ -40668,7 +40967,7 @@
1
2
- 144249
+ 144248
2
@@ -40837,11 +41136,11 @@
cil_type_annotation
- 1287048
+ 1287046
id
- 1287048
+ 1287046
annotation
@@ -40859,7 +41158,7 @@
1
2
- 1287048
+ 1287046
@@ -40885,15 +41184,15 @@
cil_getter
- 4403800
+ 4403792
prop
- 4403800
+ 4403792
method
- 4403800
+ 4403792
@@ -40907,7 +41206,7 @@
1
2
- 4403800
+ 4403792
@@ -40923,7 +41222,7 @@
1
2
- 4403800
+ 4403792
@@ -41077,23 +41376,23 @@
cil_property
- 4409961
+ 4409953
id
- 4409961
+ 4409953
parent
- 1169158
+ 1169156
name
- 1132082
+ 1132080
property_type
- 519158
+ 519157
@@ -41107,7 +41406,7 @@
1
2
- 4409961
+ 4409953
@@ -41123,7 +41422,7 @@
1
2
- 4409961
+ 4409953
@@ -41139,7 +41438,7 @@
1
2
- 4409961
+ 4409953
@@ -41155,7 +41454,7 @@
1
2
- 383218
+ 383217
2
@@ -41206,7 +41505,7 @@
2
3
- 214085
+ 214084
3
@@ -41221,7 +41520,7 @@
5
7
- 102660
+ 102659
7
@@ -41247,12 +41546,12 @@
1
2
- 452273
+ 452272
2
3
- 353995
+ 353994
3
@@ -41288,7 +41587,7 @@
1
2
- 719380
+ 719379
2
@@ -41324,12 +41623,12 @@
1
2
- 719380
+ 719379
2
3
- 187487
+ 187486
3
@@ -41344,7 +41643,7 @@
8
3695
- 66972
+ 66971
@@ -41360,7 +41659,7 @@
1
2
- 989481
+ 989479
2
@@ -41427,7 +41726,7 @@
1
2
- 316029
+ 316028
2
@@ -41874,15 +42173,15 @@
cil_local_variable
- 16916582
+ 16916551
id
- 16916582
+ 16916551
impl
- 4885274
+ 4885265
index
@@ -41890,7 +42189,7 @@
var_type
- 2173089
+ 2173085
@@ -41904,7 +42203,7 @@
1
2
- 16916582
+ 16916551
@@ -41920,7 +42219,7 @@
1
2
- 16916582
+ 16916551
@@ -41936,7 +42235,7 @@
1
2
- 16916582
+ 16916551
@@ -41952,37 +42251,37 @@
1
2
- 1994583
+ 1994580
2
3
- 848508
+ 848506
3
4
- 575586
+ 575585
4
5
- 385691
+ 385690
5
6
- 282988
+ 282987
6
9
- 410510
+ 410509
9
29
- 366448
+ 366447
29
@@ -42003,37 +42302,37 @@
1
2
- 1994583
+ 1994580
2
3
- 848508
+ 848506
3
4
- 575586
+ 575585
4
5
- 385691
+ 385690
5
6
- 282988
+ 282987
6
9
- 410510
+ 410509
9
29
- 366448
+ 366447
29
@@ -42054,27 +42353,27 @@
1
2
- 2184197
+ 2184193
2
3
- 934203
+ 934201
3
4
- 601577
+ 601576
4
5
- 367424
+ 367423
5
7
- 394760
+ 394759
7
@@ -42258,7 +42557,7 @@
1
2
- 1379208
+ 1379206
2
@@ -42273,12 +42572,12 @@
4
7
- 171064
+ 171063
7
29
- 164317
+ 164316
29
@@ -42299,12 +42598,12 @@
1
2
- 1439672
+ 1439669
2
3
- 263506
+ 263505
3
@@ -42319,7 +42618,7 @@
12
44190
- 110058
+ 110057
@@ -42335,7 +42634,7 @@
1
2
- 1482931
+ 1482929
2
@@ -42350,7 +42649,7 @@
4
8
- 175902
+ 175901
8
@@ -42418,15 +42717,15 @@
cil_handler
- 1747392
+ 1747389
id
- 1747392
+ 1747389
impl
- 1140478
+ 1140476
index
@@ -42438,15 +42737,15 @@
try_start
- 1706714
+ 1706711
try_end
- 1726066
+ 1726063
handler_start
- 1747392
+ 1747389
@@ -42460,7 +42759,7 @@
1
2
- 1747392
+ 1747389
@@ -42476,7 +42775,7 @@
1
2
- 1747392
+ 1747389
@@ -42492,7 +42791,7 @@
1
2
- 1747392
+ 1747389
@@ -42508,7 +42807,7 @@
1
2
- 1747392
+ 1747389
@@ -42524,7 +42823,7 @@
1
2
- 1747392
+ 1747389
@@ -42540,7 +42839,7 @@
1
2
- 1747392
+ 1747389
@@ -42556,7 +42855,7 @@
1
2
- 839570
+ 839568
2
@@ -42587,7 +42886,7 @@
1
2
- 839570
+ 839568
2
@@ -42618,7 +42917,7 @@
1
2
- 1067865
+ 1067863
2
@@ -42639,7 +42938,7 @@
1
2
- 853172
+ 853171
2
@@ -42670,12 +42969,12 @@
1
2
- 847185
+ 847183
2
3
- 179308
+ 179307
3
@@ -42701,7 +43000,7 @@
1
2
- 839570
+ 839568
2
@@ -43254,7 +43553,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43275,7 +43574,7 @@
1
2
- 1706714
+ 1706711
@@ -43291,7 +43590,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43312,7 +43611,7 @@
1
2
- 1694109
+ 1694106
2
@@ -43333,7 +43632,7 @@
1
2
- 1689510
+ 1689507
2
@@ -43354,7 +43653,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43375,7 +43674,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43396,7 +43695,7 @@
1
2
- 1726066
+ 1726063
@@ -43412,7 +43711,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43433,7 +43732,7 @@
1
2
- 1724634
+ 1724631
2
@@ -43454,7 +43753,7 @@
1
2
- 1726066
+ 1726063
@@ -43470,7 +43769,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43491,7 +43790,7 @@
1
2
- 1747392
+ 1747389
@@ -43507,7 +43806,7 @@
1
2
- 1747392
+ 1747389
@@ -43523,7 +43822,7 @@
1
2
- 1747392
+ 1747389
@@ -43539,7 +43838,7 @@
1
2
- 1747392
+ 1747389
@@ -43555,7 +43854,7 @@
1
2
- 1747392
+ 1747389
@@ -43571,7 +43870,7 @@
1
2
- 1747392
+ 1747389
@@ -43712,11 +44011,11 @@
cil_method_stack_size
- 19888845
+ 19888809
method
- 19888845
+ 19888809
size
@@ -43734,7 +44033,7 @@
1
2
- 19888845
+ 19888809
@@ -43805,110 +44104,110 @@
cil_public
- 22449297
+ 22449256
id
- 22449297
+ 22449256
cil_private
- 11386275
+ 11386254
id
- 11386275
+ 11386254
cil_protected
- 21117144
+ 21117106
id
- 21117144
+ 21117106
cil_internal
- 725021
+ 725019
id
- 725021
+ 725019
cil_static
- 10668456
+ 10668437
id
- 10668456
+ 10668437
cil_sealed
- 4672361
+ 4672352
id
- 4672361
+ 4672352
cil_virtual
- 8620980
+ 8620965
id
- 8620980
+ 8620965
cil_abstract
- 2076286
+ 2076282
id
- 2076286
+ 2076282
cil_class
- 3287620
+ 3287614
id
- 3287620
+ 3287614
cil_interface
- 269971
+ 269970
id
- 269971
+ 269970
@@ -43937,33 +44236,33 @@
cil_specialname
- 9198303
+ 9198286
id
- 9198303
+ 9198286
cil_newslot
- 5415106
+ 5415097
id
- 5415106
+ 5415097
cil_base_class
- 3276881
+ 3276875
id
- 3276881
+ 3276875
base
@@ -43981,7 +44280,7 @@
1
2
- 3276881
+ 3276875
@@ -44027,15 +44326,15 @@
cil_base_interface
- 2149528
+ 2149524
id
- 914265
+ 914263
base
- 395714
+ 395713
@@ -44049,7 +44348,7 @@
1
2
- 516815
+ 516814
2
@@ -44090,7 +44389,7 @@
1
2
- 263484
+ 263483
2
@@ -44208,11 +44507,11 @@
cil_type_parameter
- 1302994
+ 1302992
unbound
- 978091
+ 978090
index
@@ -44220,7 +44519,7 @@
param
- 1302994
+ 1302992
@@ -44234,7 +44533,7 @@
1
2
- 730575
+ 730573
2
@@ -44260,7 +44559,7 @@
1
2
- 730575
+ 730573
2
@@ -44408,7 +44707,7 @@
1
2
- 1302994
+ 1302992
@@ -44424,7 +44723,7 @@
1
2
- 1302994
+ 1302992
@@ -44434,11 +44733,11 @@
cil_type_argument
- 8232620
+ 8232606
bound
- 6158785
+ 6158774
index
@@ -44446,7 +44745,7 @@
t
- 2057108
+ 2057104
@@ -44460,17 +44759,17 @@
1
2
- 4348543
+ 4348535
2
3
- 1618416
+ 1618413
3
43
- 191826
+ 191825
@@ -44486,17 +44785,17 @@
1
2
- 4430311
+ 4430303
2
3
- 1586134
+ 1586131
3
43
- 142340
+ 142339
@@ -44629,12 +44928,12 @@
1
2
- 889077
+ 889076
2
3
- 538076
+ 538075
3
@@ -44670,12 +44969,12 @@
1
2
- 1655948
+ 1655945
2
3
- 368856
+ 368855
3
@@ -44781,15 +45080,15 @@
cil_attribute
- 4315762
+ 4315754
attributeid
- 4315762
+ 4315754
element
- 3808557
+ 3808550
constructor
@@ -44807,7 +45106,7 @@
1
2
- 4315762
+ 4315754
@@ -44823,7 +45122,7 @@
1
2
- 4315762
+ 4315754
@@ -44839,12 +45138,12 @@
1
2
- 3532186
+ 3532180
2
3520
- 276371
+ 276370
@@ -44860,7 +45159,7 @@
1
2
- 3535506
+ 3535499
2
@@ -45017,7 +45316,7 @@
cil_attribute_named_argument
- 221114
+ 221113
attribute_id
@@ -45064,7 +45363,7 @@
1
2
- 104462
+ 104461
2
@@ -45233,11 +45532,11 @@
cil_attribute_positional_argument
- 1300780
+ 1300778
attribute_id
- 1270982
+ 1270980
index
@@ -45259,7 +45558,7 @@
1
2
- 1243724
+ 1243722
2
@@ -45280,12 +45579,12 @@
1
2
- 1243893
+ 1243891
2
4
- 27089
+ 27088
@@ -45409,11 +45708,11 @@
metadata_handle
- 80614656
+ 80614512
entity
- 80367053
+ 80366908
location
@@ -45421,7 +45720,7 @@
handle
- 2025043
+ 2025039
@@ -45435,7 +45734,7 @@
1
2
- 80240940
+ 80240796
2
@@ -45456,7 +45755,7 @@
1
2
- 80243283
+ 80243139
2
@@ -45634,7 +45933,7 @@
4
5
- 264981
+ 264980
5
@@ -45649,7 +45948,7 @@
11
15
- 171194
+ 171193
15
@@ -45664,7 +45963,7 @@
25
39
- 158763
+ 158762
39
@@ -45700,12 +45999,12 @@
1
2
- 274505
+ 274504
2
3
- 266044
+ 266043
3
@@ -45720,7 +46019,7 @@
6
8
- 171194
+ 171193
8
@@ -45750,7 +46049,7 @@
37
70
- 154207
+ 154206
70
@@ -45764,4 +46063,4 @@
-
+
\ No newline at end of file
From 548a62d1ab27ffd71dde73e8e40a115109720a11 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 17 Jan 2022 16:48:11 +0000
Subject: [PATCH 061/296] C++: Fix branch related FPs in
cpp/improper-null-termination.
---
.../ImproperNullTermination.ql | 46 +++++++++++++++++--
.../ImproperNullTermination.expected | 4 --
.../ImproperNullTermination/test.cpp | 8 ++--
3 files changed, 45 insertions(+), 13 deletions(-)
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
index ed378dce60a..f51c47cf70e 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
@@ -23,6 +23,10 @@ DeclStmt declWithNoInit(LocalVariable v) {
not exists(v.getInitializer())
}
+/**
+ * Flow from a buffer that is not not null terminated to a sink that requires
+ * null termination.
+ */
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
@@ -52,12 +56,44 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
exprDefinition(v, node, _) or
- mayAddNullTerminator(node, v.getAnAccess()) or
- node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken
isSinkActual(node, v) // only report first use
}
}
-from ImproperNullTerminationReachability r, LocalVariable v, VariableAccess va
-where r.reaches(_, v, va)
-select va, "Variable $@ may not be null terminated.", v, v.getName()
+/**
+ * Flow from a place where null termination is added, to a sink of
+ * `ImproperNullTerminationReachability`. This was previously implemented as a
+ * simple barrier in `ImproperNullTerminationReachability`, but there were
+ * false positive results involving multiple paths from source to sink. We'd
+ * prefer to report only the results we are sure of.
+ */
+class NullTerminationReachability extends StackVariableReachabilityWithReassignment {
+ NullTerminationReachability() { this = "NullTerminationReachability" }
+
+ override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
+ mayAddNullTerminator(node, v.getAnAccess()) or // null termination
+ node.(AddressOfExpr).getOperand() = v.getAnAccess() // address taken (possible null termination)
+ }
+
+ override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
+ // have the same sinks as `ImproperNullTerminationReachability`.
+ exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
+ }
+
+ override predicate isBarrier(ControlFlowNode node, StackVariable v) {
+ // don't look further back than the source, or further forward than the sink
+ exists(ImproperNullTerminationReachability r | r.isSourceActual(node, v)) or
+ exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
+ }
+}
+
+from
+ ImproperNullTerminationReachability reaches, NullTerminationReachability nullTermReaches,
+ ControlFlowNode source, LocalVariable v, VariableAccess sink
+where
+ reaches.reaches(source, v, sink) and
+ not exists(ControlFlowNode termination |
+ nullTermReaches.reaches(termination, _, sink) and
+ termination != source
+ )
+select sink, "Variable $@ may not be null terminated.", v, v.getName()
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
index 0325ba89a22..beaa1033eb2 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
+++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
@@ -18,10 +18,6 @@
| test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 |
| test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer |
| test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer |
-| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer |
-| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer |
-| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer |
-| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer |
| test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 |
| test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer |
| test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer |
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
index 88fbc46119b..49dc01a40df 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
+++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
@@ -352,7 +352,7 @@ void test_strlen(bool cond1, bool cond2)
if (cond1)
buffer[0] = 0;
if (cond1)
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
{
@@ -361,7 +361,7 @@ void test_strlen(bool cond1, bool cond2)
if (cond1)
buffer[0] = 0;
if (cond2)
- strlen(buffer); // BAD
+ strlen(buffer); // BAD [NOT DETECTED]
}
{
@@ -389,7 +389,7 @@ void test_strlen(bool cond1, bool cond2)
if (init != 0)
{
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
}
@@ -407,7 +407,7 @@ void test_strlen(bool cond1, bool cond2)
{
// ...
} else {
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
}
}
From ea7945bac10055da69d6968a0ddb2b987ff6d7e8 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:21:07 +0100
Subject: [PATCH 062/296] QL: show recommendation queries by default, and
remove the MissingQLDoc query
---
ql/ql/src/codeql-suites/ql-code-scanning.qls | 1 +
ql/ql/src/queries/style/docs/MissingQLDoc.ql | 25 --------------------
2 files changed, 1 insertion(+), 25 deletions(-)
delete mode 100644 ql/ql/src/queries/style/docs/MissingQLDoc.ql
diff --git a/ql/ql/src/codeql-suites/ql-code-scanning.qls b/ql/ql/src/codeql-suites/ql-code-scanning.qls
index f6b2a097b0a..f9e4f729d3e 100644
--- a/ql/ql/src/codeql-suites/ql-code-scanning.qls
+++ b/ql/ql/src/codeql-suites/ql-code-scanning.qls
@@ -12,6 +12,7 @@
problem.severity:
- error
- warning
+ - recommendation
- exclude:
deprecated: //
- exclude:
diff --git a/ql/ql/src/queries/style/docs/MissingQLDoc.ql b/ql/ql/src/queries/style/docs/MissingQLDoc.ql
deleted file mode 100644
index c7da02073a3..00000000000
--- a/ql/ql/src/queries/style/docs/MissingQLDoc.ql
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @name Missing QLDoc.
- * @description Library classes should have QLDoc.
- * @kind problem
- * @problem.severity recommendation
- * @id ql/missing-qldoc
- * @tags maintainability
- * @precision high
- */
-
-import ql
-
-from File f, Class c
-where
- f = c.getLocation().getFile() and
- not exists(c.getQLDoc()) and // no QLDoc
- f.getExtension() = "qll" and // in a library
- not c.isPrivate() and // class is public
- not exists(Module m |
- m.getAMember*() = c and
- m.isPrivate() // modules containing the class are public
- ) and
- not exists(c.getAliasType()) and // class is not just an alias
- not f.getParentContainer*().getBaseName().toLowerCase() = ["internal", "experimental", "test"] // exclusions
-select c, "This library class should have QLDoc."
From 95ae1139943770cb5410d01f3d87db537e4a730b Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:22:01 +0100
Subject: [PATCH 063/296] QL: downgrade redundant-inline-cast to a warning
query
---
ql/ql/src/queries/style/RedundantInlineCast.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ql/ql/src/queries/style/RedundantInlineCast.ql b/ql/ql/src/queries/style/RedundantInlineCast.ql
index 29dc83e52de..ae307b408b8 100644
--- a/ql/ql/src/queries/style/RedundantInlineCast.ql
+++ b/ql/ql/src/queries/style/RedundantInlineCast.ql
@@ -2,7 +2,7 @@
* @name Redundant inline cast
* @description Redundant inline casts
* @kind problem
- * @problem.severity error
+ * @problem.severity warning
* @id ql/redundant-inline-cast
* @tags maintainability
* @precision high
From 1ec868eeaea162ccdf41a3958beb281ce7385407 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:23:33 +0100
Subject: [PATCH 064/296] QL: various improvements to Ast.qll
---
ql/ql/src/codeql_ql/ast/Ast.qll | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll
index f0821d063fa..be2973d5ddf 100644
--- a/ql/ql/src/codeql_ql/ast/Ast.qll
+++ b/ql/ql/src/codeql_ql/ast/Ast.qll
@@ -63,6 +63,9 @@ class AstNode extends TAstNode {
pred = directMember("getQLDoc") and result = this.getQLDoc()
}
+ /** Gets any child of this node. */
+ AstNode getAChild() { result = this.getAChild(_) }
+
/**
* Gets the primary QL class for the ast node.
*/
@@ -1238,14 +1241,7 @@ class Boolean extends Literal {
/** A comparison symbol, such as `"<"` or `"="`. */
class ComparisonSymbol extends string {
- ComparisonSymbol() {
- this = "=" or
- this = "!=" or
- this = "<" or
- this = ">" or
- this = "<=" or
- this = ">="
- }
+ ComparisonSymbol() { this = ["=", "!=", "<", ">", "<=", ">="] }
}
/** A comparison formula, such as `x < 3` or `y = true`. */
@@ -1287,10 +1283,7 @@ class Quantifier extends TQuantifier, Formula {
}
/** Gets the ith variable declaration of this quantifier. */
- VarDecl getArgument(int i) {
- i >= 1 and
- toQL(result) = quant.getChild(i - 1)
- }
+ VarDecl getArgument(int i) { toQL(result) = quant.getChild(i + 1) }
/** Gets an argument of this quantifier. */
VarDecl getAnArgument() { result = this.getArgument(_) }
@@ -1661,6 +1654,15 @@ class FullAggregate extends TFullAggregate, Aggregate {
}
}
+/**
+ * A "any" expression, such as `any(int i | i > 0).toString()`.
+ */
+class Any extends FullAggregate {
+ Any() { this.getKind() = "any" }
+
+ override string getAPrimaryQlClass() { result = "Any" }
+}
+
/**
* A "rank" expression, such as `rank[4](int i | i = [5 .. 15] | i)`.
*/
@@ -1855,7 +1857,7 @@ class ExprAnnotation extends TExprAnnotation, Expr {
/** A function symbol, such as `+` or `*`. */
class FunctionSymbol extends string {
- FunctionSymbol() { this = "+" or this = "-" or this = "*" or this = "/" or this = "%" }
+ FunctionSymbol() { this = ["+", "-", "*", "/", "%"] }
}
/**
From a1f4c85deaeb8dfe6534bc679527b38544f545db Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:37:04 +0100
Subject: [PATCH 065/296] QL: update expected output for the printAst test
---
ql/ql/test/printAst/printAst.expected | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/ql/ql/test/printAst/printAst.expected b/ql/ql/test/printAst/printAst.expected
index 45e8497dfad..3d1e86a7c92 100644
--- a/ql/ql/test/printAst/printAst.expected
+++ b/ql/ql/test/printAst/printAst.expected
@@ -121,8 +121,8 @@ nodes
| Foo.qll:22:3:22:3 | f | semmle.order | 60 |
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 60 |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | [FullAggregate[any]] FullAggregate[any] |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 62 |
+| Foo.qll:22:7:22:16 | Any | semmle.label | [Any] Any |
+| Foo.qll:22:7:22:16 | Any | semmle.order | 62 |
| Foo.qll:22:11:22:13 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
| Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 63 |
| Foo.qll:22:11:22:15 | f | semmle.label | [VarDecl] f |
@@ -363,10 +363,10 @@ edges
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.order | 59 |
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.label | getLeftOperand() |
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.order | 60 |
-| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | getRightOperand() |
-| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 62 |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.label | getArgument(_) |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.order | 63 |
+| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Any | semmle.label | getRightOperand() |
+| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Any | semmle.order | 62 |
+| Foo.qll:22:7:22:16 | Any | Foo.qll:22:11:22:15 | f | semmle.label | getArgument(_) |
+| Foo.qll:22:7:22:16 | Any | Foo.qll:22:11:22:15 | f | semmle.order | 63 |
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | getTypeExpr() |
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 63 |
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.label | getLeftOperand() |
From 14d2f5fe0280ec4c8e07cb301cc3c0ed90bf21ba Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:37:32 +0100
Subject: [PATCH 066/296] QL: add a new ql/could-be-cast query
---
.../src/codeql_ql/style/CouldBeCastQuery.qll | 53 +++++++++++++++++++
ql/ql/src/queries/style/CouldBeCast.ql | 23 ++++++++
.../style/CouldBeCast/CouldBeCast.expected | 3 ++
.../style/CouldBeCast/CouldBeCast.qlref | 1 +
ql/ql/test/queries/style/CouldBeCast/Foo.qll | 19 +++++++
5 files changed, 99 insertions(+)
create mode 100644 ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
create mode 100644 ql/ql/src/queries/style/CouldBeCast.ql
create mode 100644 ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
create mode 100644 ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
create mode 100644 ql/ql/test/queries/style/CouldBeCast/Foo.qll
diff --git a/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll b/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
new file mode 100644
index 00000000000..1ad2157c4dc
--- /dev/null
+++ b/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
@@ -0,0 +1,53 @@
+import ql
+
+/**
+ * Holds if `aggr` is of one of the following forms:
+ * `exists(var | range)` or `any(var | range)` or `any(var | | range)` or `any(type x | .. | x)`
+ */
+private predicate castAggregate(AstNode aggr, Formula range, VarDecl var, string kind) {
+ kind = "exists" and
+ exists(Exists ex | aggr = ex |
+ ex.getRange() = range and
+ not exists(ex.getFormula()) and
+ count(ex.getArgument(_)) = 1 and
+ ex.getArgument(0) = var
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ not exists(anyy.getRange()) and
+ anyy.getExpr(0) = range and
+ count(anyy.getExpr(_)) = 1 and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getArgument(0) = var
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ range = anyy.getRange() and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getArgument(0) = var and
+ not exists(anyy.getExpr(0))
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ range = anyy.getRange() and
+ count(anyy.getExpr(_)) = 1 and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getExpr(_).(VarAccess).getDeclaration() = var and
+ anyy.getArgument(0) = var
+ )
+}
+
+/** Holds if `aggr` is an aggregate that could be replaced with an instanceof expression or an inline cast. */
+predicate aggregateCouldBeCast(
+ AstNode aggr, ComparisonFormula comp, string kind, VarDecl var, AstNode operand
+) {
+ castAggregate(aggr, comp, var, kind) and
+ comp.getOperator() = "=" and
+ count(VarAccess access | access.getDeclaration() = var and access.getParent() != aggr) = 1 and
+ comp.getAnOperand().(VarAccess).getDeclaration() = var and
+ operand = comp.getAnOperand() and
+ not operand.(VarAccess).getDeclaration() = var
+}
diff --git a/ql/ql/src/queries/style/CouldBeCast.ql b/ql/ql/src/queries/style/CouldBeCast.ql
new file mode 100644
index 00000000000..73eeaf0a90f
--- /dev/null
+++ b/ql/ql/src/queries/style/CouldBeCast.ql
@@ -0,0 +1,23 @@
+/**
+ * @name Expression can be replaced with a cast
+ * @description An exists/any that is only used to cast a value to a type
+ * can be replaced with a cast.
+ * @kind problem
+ * @problem.severity warning
+ * @id ql/could-be-cast
+ * @precision very-high
+ */
+
+import ql
+import codeql_ql.style.CouldBeCastQuery
+
+from AstNode aggr, VarDecl var, string msg
+where
+ exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, _) |
+ kind = "exists" and
+ msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
+ or
+ kind = "any" and
+ msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
+ )
+select aggr, msg, var, var.getName()
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
new file mode 100644
index 00000000000..41792f6892d
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
@@ -0,0 +1,3 @@
+| Foo.qll:3:3:3:24 | Exists | The assignment to $@ in the exists(..) can replaced with an instanceof expression. | Foo.qll:3:10:3:15 | j | j |
+| Foo.qll:7:3:7:21 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:7:7:7:12 | j | j |
+| Foo.qll:9:3:9:25 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:9:7:9:12 | j | j |
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
new file mode 100644
index 00000000000..78879bb0ab0
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
@@ -0,0 +1 @@
+queries/style/CouldBeCast.ql
\ No newline at end of file
diff --git a/ql/ql/test/queries/style/CouldBeCast/Foo.qll b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
new file mode 100644
index 00000000000..1bd94cfd829
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
@@ -0,0 +1,19 @@
+bindingset[i]
+predicate foo(int i) {
+ exists(Even j | j = i) // NOT OK
+ or
+ exists(Even j | j = i | j % 4 = 0) // OK
+ or
+ any(Even j | j = i) = 2 // NOT OK
+ or
+ any(Even j | j = i | j) = 2 // NOT OK
+ or
+ any(Even j | j = i | j * 2) = 4 // OK
+ or
+ any(Even j | j = i and j % 4 = 0 | j) = 4 // OK
+}
+
+class Even extends int {
+ bindingset[this]
+ Even() { this % 2 = 0 }
+}
From 92f5a5f893db792be3074997378a99330d7fcb38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 13:43:17 +0100
Subject: [PATCH 067/296] Reduce FPs in IncorrectPrivilegeAssignment.ql
Implements suggestions from https://github.com/github/codeql/pull/6949#issuecomment-976482965
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 72c7f359b47..9c0481702f7 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -53,7 +53,13 @@ where
fctmp.getTarget().hasGlobalOrStdName("fopen") or
fctmp.getTarget().hasGlobalOrStdName("open")
) and
- not fctmp.getArgument(1).getValue().matches("r%") and
+ (
+ fctmp.getArgument(1).getValue().matches("%a%") or
+ // unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
+ // https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
+ // this may introduce false negatives
+ fctmp.getArgument(1).getValueText().matches("%O_APPEND%")
+ ) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
fcsnd = fctmp
From 30d896bdbbf2f436e498f1db39537012c4efc5e0 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 14:25:43 +0100
Subject: [PATCH 068/296] QL: make the alert-message more precise when the
type-cast is also redundant
---
ql/ql/src/queries/style/CouldBeCast.ql | 12 ++++++++----
.../queries/style/CouldBeCast/CouldBeCast.expected | 2 ++
ql/ql/test/queries/style/CouldBeCast/Foo.qll | 4 ++++
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/ql/ql/src/queries/style/CouldBeCast.ql b/ql/ql/src/queries/style/CouldBeCast.ql
index 73eeaf0a90f..a5c0d6c6607 100644
--- a/ql/ql/src/queries/style/CouldBeCast.ql
+++ b/ql/ql/src/queries/style/CouldBeCast.ql
@@ -11,13 +11,17 @@
import ql
import codeql_ql.style.CouldBeCastQuery
-from AstNode aggr, VarDecl var, string msg
+from AstNode aggr, VarDecl var, string msg, Expr operand
where
- exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, _) |
+ exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, operand) |
kind = "exists" and
- msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
+ if operand.getType().getASuperType*() = var.getType()
+ then msg = "The assignment in the exists(..) is redundant."
+ else msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
or
kind = "any" and
- msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
+ if operand.getType().getASuperType*() = var.getType()
+ then msg = "The assignment in the any(..) is redundant."
+ else msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
)
select aggr, msg, var, var.getName()
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
index 41792f6892d..83792e2fa46 100644
--- a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
@@ -1,3 +1,5 @@
| Foo.qll:3:3:3:24 | Exists | The assignment to $@ in the exists(..) can replaced with an instanceof expression. | Foo.qll:3:10:3:15 | j | j |
| Foo.qll:7:3:7:21 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:7:7:7:12 | j | j |
| Foo.qll:9:3:9:25 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:9:7:9:12 | j | j |
+| Foo.qll:15:3:15:20 | Any | The assignment in the any(..) is redundant. | Foo.qll:15:7:15:11 | j | j |
+| Foo.qll:17:3:17:23 | Exists | The assignment in the exists(..) is redundant. | Foo.qll:17:10:17:14 | j | j |
diff --git a/ql/ql/test/queries/style/CouldBeCast/Foo.qll b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
index 1bd94cfd829..5f6771f0043 100644
--- a/ql/ql/test/queries/style/CouldBeCast/Foo.qll
+++ b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
@@ -11,6 +11,10 @@ predicate foo(int i) {
any(Even j | j = i | j * 2) = 4 // OK
or
any(Even j | j = i and j % 4 = 0 | j) = 4 // OK
+ or
+ any(int j | j = i) = 2 // NOT OK
+ or
+ exists(int j | j = i) // NOT OK
}
class Even extends int {
From 47697f59c150882a5d7c530072f1cad30bff0544 Mon Sep 17 00:00:00 2001
From: Jeff Gran
Date: Sat, 13 Nov 2021 13:42:17 -0700
Subject: [PATCH 069/296] Ruby: Add classes for detecting user input from
`graphql-ruby`
---
ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 +
.../ql/lib/codeql/ruby/frameworks/GraphQL.qll | 422 ++++++++++++++++++
.../library-tests/frameworks/GraphQL.expected | 46 ++
.../test/library-tests/frameworks/GraphQL.ql | 36 ++
.../frameworks/StandardLibrary.expected | 9 +
.../app/graphql/mutations/base_mutation.rb | 8 +
.../frameworks/app/graphql/mutations/dummy.rb | 14 +
.../frameworks/app/graphql/resolvers/base.rb | 4 +
.../app/graphql/resolvers/dummy_resolver.rb | 15 +
.../app/graphql/types/base_argument.rb | 4 +
.../app/graphql/types/base_field.rb | 5 +
.../app/graphql/types/base_input_object.rb | 5 +
.../app/graphql/types/base_interface.rb | 7 +
.../app/graphql/types/base_object.rb | 5 +
.../app/graphql/types/mutation_type.rb | 5 +
.../app/graphql/types/query_type.rb | 46 ++
.../cwe-078/CommandInjection.expected | 8 +
.../security/cwe-078/CommandInjection.rb | 38 ++
18 files changed, 678 insertions(+)
create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
create mode 100644 ruby/ql/test/library-tests/frameworks/GraphQL.expected
create mode 100644 ruby/ql/test/library-tests/frameworks/GraphQL.ql
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll
index 8939bacf23b..70bb35f4651 100644
--- a/ruby/ql/lib/codeql/ruby/Frameworks.qll
+++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll
@@ -6,6 +6,7 @@ private import codeql.ruby.frameworks.ActionController
private import codeql.ruby.frameworks.ActiveRecord
private import codeql.ruby.frameworks.ActiveStorage
private import codeql.ruby.frameworks.ActionView
+private import codeql.ruby.frameworks.GraphQL
private import codeql.ruby.frameworks.Rails
private import codeql.ruby.frameworks.StandardLibrary
private import codeql.ruby.frameworks.Files
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
new file mode 100644
index 00000000000..e6779b65a0f
--- /dev/null
+++ b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
@@ -0,0 +1,422 @@
+private import codeql.ruby.AST
+private import codeql.ruby.Concepts
+private import codeql.ruby.controlflow.CfgNodes
+private import codeql.ruby.DataFlow
+private import codeql.ruby.dataflow.RemoteFlowSources
+private import codeql.ruby.ast.internal.Module
+private import codeql.ruby.ApiGraphs
+
+private class GraphqlRelayClassicMutationAccess extends ConstantReadAccess {
+ //GraphQL::Schema::RelayClassicMutation
+ GraphqlRelayClassicMutationAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("RelayClassicMutation")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+private class GraphqlSchemaResolverAccess extends ConstantReadAccess {
+ //GraphQL::Schema::Resolver
+ GraphqlSchemaResolverAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("Resolver")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+private class GraphqlSchemaObjectAccess extends ConstantReadAccess {
+ //GraphQL::Schema::Object
+ GraphqlSchemaObjectAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("Object")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::RelayClassicMutation`.
+ * For example,
+ *
+ * ```rb
+ * module Mutations
+ * class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ * argument_class Types::BaseArgument
+ * field_class Types::BaseField
+ * input_object_class Types::BaseInputObject
+ * object_class Types::BaseObject
+ * end
+ * end
+ *
+ * module Mutation
+ * class MyMutation < BaseMutation
+ * argument :something_id, ID, required: false
+ * field :success, Boolean, null: false
+ *
+ * def resolve(something_id:)
+ * # call your application logic here...
+ * end
+ * end
+ * end
+ * ```
+ */
+private class GraphqlRelayClassicMutationClass extends ClassDeclaration {
+ GraphqlRelayClassicMutationClass() {
+ // class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ this.getSuperclassExpr() instanceof GraphqlRelayClassicMutationAccess
+ or
+ // class MyMutation < BaseMutation
+ exists(GraphqlRelayClassicMutationClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::Resolver`.
+ * For example,
+ *
+ * ```rb
+ * module Resolvers
+ * class Base < GraphQL::Schema::Resolver
+ * argument_class Arguments::Base
+ * end
+ * end
+ *
+ * module Resolvers
+ * class RecommendedItems < Resolvers::Base
+ * type [Types::Item], null: false
+ * argument :order_by, Types::ItemOrder, required: false
+ *
+ * def resolve(order_by: )
+ * # call your application logic here...
+ * end
+ * end
+ * end
+ * ```
+ */
+private class GraphqlSchemaResolverClass extends ClassDeclaration {
+ GraphqlSchemaResolverClass() {
+ // class BaseResolver < GraphQL::Schema::Resolver
+ this.getSuperclassExpr() instanceof GraphqlSchemaResolverAccess
+ or
+ // class MyResolver < BaseResolver
+ exists(GraphqlSchemaResolverClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::Object`.
+ * For example,
+ *
+ * ```rb
+ * class BaseObject < GraphQL::Schema::Object
+ * field_class BaseField
+ * end
+ *
+ * class Musician < BaseObject
+ * field :favorite_key, Key
+ * end
+ * ```
+ */
+class GraphqlSchemaObjectClass extends ClassDeclaration {
+ GraphqlSchemaObjectClass() {
+ // class BaseObject < GraphQL::Schema::Object
+ this.getSuperclassExpr() instanceof GraphqlSchemaObjectAccess
+ or
+ // class MyObject < BaseObject
+ exists(GraphqlSchemaObjectClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+
+ /** Gets a `GraphqlFieldDefinitionMethodCall` called in this class. */
+ GraphqlFieldDefinitionMethodCall getAFieldDefinitionMethodCall() {
+ result.getReceiverClass() = this
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * Both of these classes have an overrideable `resolve` instance
+ * method which can receive user input in order to resolve a query or mutation.
+ */
+private class GraphqlResolvableClass extends ClassDeclaration {
+ GraphqlResolvableClass() {
+ this instanceof GraphqlRelayClassicMutationClass or
+ this instanceof GraphqlSchemaResolverClass
+ }
+}
+
+/**
+ * A `resolve` instance method on a sub-class of either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * This `resolve` method is essentially an HTTP request handler.
+ * The user input data comes in through a GraphQL query, is parsed by the GraphQL
+ * library, and this method handles the request. Then the result is serialized
+ * into a GraphQL response on the way out.
+ *
+ * For example:
+ *
+ * ```rb
+ * module Mutation
+ * class NameAnInstrument < BaseMutationn
+ * argument :instrument_uuid, Types::Uuid,
+ * required: true,
+ * loads: ::Instrument,
+ * as: :instrument,
+ * argument :name, String, required: true
+ *
+ * def load_instrument(uuid)
+ * ::Instrument.find_by(uuid: uuid)
+ * end
+ *
+ * # GraphqlResolveMethod
+ * def resolve(instrument:, name:)
+ * instrument.set_name(name)
+ * end
+ * end
+ * end
+ * ```
+ */
+class GraphqlResolveMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlResolvableClass resolvableClass;
+
+ GraphqlResolveMethod() { this = resolvableClass.getMethod("resolve") }
+
+ override Parameter getARoutedParameter() { result = this.getAParameter() }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the mutation class containing this method. */
+ GraphqlResolvableClass getMutationClass() { result = resolvableClass }
+}
+
+/**
+ * A `load_*` method on a sub-class of either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * This method takes user input (some kind of ID or specifier) and is intended
+ * to resolve the domain object using that ID.
+ *
+ * For example:
+ *
+ * ```rb
+ * module Mutation
+ * class NameAnInstrument < BaseMutationn
+ * argument :instrument_uuid, Types::Uuid,
+ * required: true,
+ * loads: ::Instrument,
+ * as: :instrument,
+ * argument :name, String, required: true
+ *
+ * # GraphqlLoadMethod
+ * def load_instrument(uuid)
+ * ::Instrument.find_by(uuid: uuid)
+ * end
+ *
+ * def resolve(instrument:, name:)
+ * instrument.set_name(name)
+ * end
+ * end
+ * end
+ * ```
+ */
+class GraphqlLoadMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlResolvableClass resolvableClass;
+
+ GraphqlLoadMethod() {
+ this.getEnclosingModule() = resolvableClass and
+ this.getName().regexpMatch("^load_.*")
+ }
+
+ override Parameter getARoutedParameter() { result = this.getAParameter() }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the mutation class containing this method. */
+ GraphqlResolvableClass getMutationClass() { result = resolvableClass }
+}
+
+/**
+ * A `MethodCall` that represents calling a class method on a
+ * a sub-class of `GraphQL::Schema::Object`
+ */
+private class GraphqlSchemaObjectClassMethodCall extends MethodCall {
+ private GraphqlSchemaObjectClass recvCls;
+
+ GraphqlSchemaObjectClassMethodCall() {
+ // e.g. Foo.some_method(...)
+ recvCls.getModule() = resolveConstantReadAccess(this.getReceiver())
+ or
+ // e.g. self.some_method(...) within a graphql Object or Interface
+ this.getReceiver() instanceof Self and
+ this.getEnclosingModule() = recvCls
+ }
+
+ /** Gets the `GraphqlSchemaObjectClass` representing the receiver of this method. */
+ GraphqlSchemaObjectClass getReceiverClass() { result = recvCls }
+}
+
+/**
+ * A `MethodCall` that represents calling the class method `field` on a GraphQL
+ * object.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * # GraphqlFieldDefinitionMethodCall
+ * field :email, String
+ * end
+ * ```
+ *
+ * See also: https://graphql-ruby.org/fields/introduction.html
+ */
+class GraphqlFieldDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCall {
+ GraphqlFieldDefinitionMethodCall() { this.getMethodName() = "field" }
+
+ /** Gets the name of this GraphQL field. */
+ string getFieldName() { result = this.getArgument(0).getValueText() }
+}
+
+/**
+ * A `MethodCall` that represents calling the class method `argument` inside the
+ * block for a `field` definition on a GraphQL object.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * # GraphqlFieldArgumentDefinitionMethodCall
+ * argument :starts_with, String, "Show only friends matching the given prefix"
+ * end
+ * end
+ * ```
+ *
+ * See Also: https://graphql-ruby.org/fields/arguments
+ */
+private class GraphqlFieldArgumentDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCall {
+ private GraphqlFieldDefinitionMethodCall fieldDefinition;
+
+ GraphqlFieldArgumentDefinitionMethodCall() {
+ this.getMethodName() = "argument" and
+ fieldDefinition.getBlock() = this.getEnclosingCallable()
+ }
+
+ /** Gets the method call that defines the GraphQL field this argument is for */
+ GraphqlFieldDefinitionMethodCall getFieldDefinition() { result = fieldDefinition }
+
+ /** Gets the name of the field which this is an argument for */
+ string getFieldName() { result = this.getFieldDefinition().getFieldName() }
+
+ /** Gets the name of the argument (i.e. the first argument to this `argument` method call) */
+ string getArgumentName() { result = this.getArgument(0).(SymbolLiteral).getValueText() }
+}
+
+/**
+ * A `Method` which represents an instance method which is the resolver method for a
+ * GraphQL `field`.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * argument :starts_with, String, "Show only friends matching the given prefix"
+ * end
+ *
+ * # GraphqlFieldResolutionMethod
+ * def friends(starts_with:)
+ * object.friends.where("name like #{starts_with}")
+ * end
+ * end
+ * ```
+ *
+ * or:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * argument :starts_with, String, "Show only friends matching the given prefix",
+ * resolver_method: :my_custom_method, extras: [:graphql_name]
+ * end
+ *
+ * # GraphqlFieldResolutionMethod
+ * def my_custom_method(**args)
+ * puts args[:graphql_name] # for debugging
+ * object.friends.where("name like #{args[:starts_with]}")
+ * end
+ * end
+ * ```
+ */
+class GraphqlFieldResolutionMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlSchemaObjectClass schemaObjectClass;
+
+ GraphqlFieldResolutionMethod() {
+ this.getEnclosingModule() = schemaObjectClass and
+ exists(GraphqlFieldDefinitionMethodCall defn |
+ // field :foo, resolver_method: :custom_method
+ // def custom_method(...)
+ defn.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
+ or
+ // field :foo
+ // def foo(...)
+ not exists(defn.getKeywordArgument("resolver_method").(SymbolLiteral)) and
+ defn.getFieldName() = this.getName()
+ )
+ }
+
+ /** Gets the method call which is the definition of the field corresponding to this resolver method. */
+ GraphqlFieldDefinitionMethodCall getDefinition() {
+ result.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
+ or
+ not exists(result.getKeywordArgument("resolver_method").(SymbolLiteral)) and
+ result.getFieldName() = this.getName()
+ }
+
+ // check for a named argument the same name as a defined argument for this field
+ override Parameter getARoutedParameter() {
+ result = this.getAParameter() and
+ exists(GraphqlFieldArgumentDefinitionMethodCall argDefn |
+ argDefn.getEnclosingCallable() = this.getDefinition().getBlock() and
+ (
+ result.(KeywordParameter).hasName(argDefn.getArgumentName())
+ or
+ // TODO this will cause false positives because now *anything* in the **args
+ // param will be flagged as as RoutedParameter/RemoteFlowSource, but really
+ // only the hash keys corresponding to the defined arguments are user input
+ // others could be things defined in the `:extras` keyword argument to the `argument`
+ result instanceof HashSplatParameter // often you see `def field(**args)`
+ )
+ )
+ }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the class containing this method. */
+ GraphqlSchemaObjectClass getGraphqlClass() { result = schemaObjectClass }
+}
diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.expected b/ruby/ql/test/library-tests/frameworks/GraphQL.expected
new file mode 100644
index 00000000000..173f3846f9a
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/GraphQL.expected
@@ -0,0 +1,46 @@
+graphqlSchemaObjectClass
+| app/graphql/types/base_object.rb:2:3:4:5 | BaseObject |
+| app/graphql/types/mutation_type.rb:2:3:4:5 | MutationType |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType |
+graphqlSchemaObjectFieldDefinition
+| app/graphql/types/mutation_type.rb:2:3:4:5 | MutationType | app/graphql/types/mutation_type.rb:3:5:3:44 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:3:5:5:40 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:32:5:35:7 | call to field |
+graphqlResolveMethod
+| app/graphql/mutations/dummy.rb:9:5:12:7 | resolve |
+| app/graphql/resolvers/dummy_resolver.rb:10:5:13:7 | resolve |
+graphqlResolveMethodRoutedParameter
+| app/graphql/mutations/dummy.rb:9:5:12:7 | resolve | app/graphql/mutations/dummy.rb:9:17:9:25 | something |
+| app/graphql/resolvers/dummy_resolver.rb:10:5:13:7 | resolve | app/graphql/resolvers/dummy_resolver.rb:10:17:10:25 | something |
+graphqlLoadMethod
+| app/graphql/mutations/dummy.rb:5:5:7:7 | load_something |
+| app/graphql/resolvers/dummy_resolver.rb:6:5:8:7 | load_something |
+graphqlLoadMethodRoutedParameter
+| app/graphql/mutations/dummy.rb:5:5:7:7 | load_something | app/graphql/mutations/dummy.rb:5:24:5:25 | id |
+| app/graphql/resolvers/dummy_resolver.rb:6:5:8:7 | load_something | app/graphql/resolvers/dummy_resolver.rb:6:24:6:25 | id |
+graphqlFieldDefinitionMethodCall
+| app/graphql/types/mutation_type.rb:3:5:3:44 | call to field |
+| app/graphql/types/query_type.rb:3:5:5:40 | call to field |
+| app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:32:5:35:7 | call to field |
+graphqlFieldResolutionMethod
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg |
+graphqlFieldResolutionRoutedParameter
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg | app/graphql/types/query_type.rb:10:18:10:23 | number |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method | app/graphql/types/query_type.rb:18:23:18:33 | blah_number |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat | app/graphql/types/query_type.rb:27:20:27:25 | **args |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:36:34:36:37 | arg1 |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:36:41:36:46 | **rest |
+graphqlFieldResolutionDefinition
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg | app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method | app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat | app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:32:5:35:7 | call to field |
diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.ql b/ruby/ql/test/library-tests/frameworks/GraphQL.ql
new file mode 100644
index 00000000000..b443d923222
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/GraphQL.ql
@@ -0,0 +1,36 @@
+private import codeql.ruby.frameworks.GraphQL
+private import codeql.ruby.AST
+
+query predicate graphqlSchemaObjectClass(GraphqlSchemaObjectClass cls) { any() }
+
+query predicate graphqlSchemaObjectFieldDefinition(
+ GraphqlSchemaObjectClass cls, GraphqlFieldDefinitionMethodCall meth
+) {
+ cls.getAFieldDefinitionMethodCall() = meth
+}
+
+query predicate graphqlResolveMethod(GraphqlResolveMethod meth) { any() }
+
+query predicate graphqlResolveMethodRoutedParameter(GraphqlResolveMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlLoadMethod(GraphqlLoadMethod meth) { any() }
+
+query predicate graphqlLoadMethodRoutedParameter(GraphqlLoadMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlFieldDefinitionMethodCall(GraphqlFieldDefinitionMethodCall cls) { any() }
+
+query predicate graphqlFieldResolutionMethod(GraphqlFieldResolutionMethod cls) { any() }
+
+query predicate graphqlFieldResolutionRoutedParameter(GraphqlFieldResolutionMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlFieldResolutionDefinition(
+ GraphqlFieldResolutionMethod meth, GraphqlFieldDefinitionMethodCall def
+) {
+ meth.getDefinition() = def
+}
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
index 36fea1b31cd..039e9019886 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
@@ -19,6 +19,15 @@ kernelSystemCallExecutions
| CommandExecution.rb:19:1:19:59 | call to system |
| CommandExecution.rb:20:1:20:62 | call to system |
| CommandExecution.rb:21:1:21:72 | call to system |
+| app/graphql/mutations/dummy.rb:10:7:10:33 | call to system |
+| app/graphql/resolvers/dummy_resolver.rb:11:7:11:33 | call to system |
+| app/graphql/types/query_type.rb:11:7:11:30 | call to system |
+| app/graphql/types/query_type.rb:19:7:19:35 | call to system |
+| app/graphql/types/query_type.rb:20:7:20:30 | call to system |
+| app/graphql/types/query_type.rb:28:7:28:40 | call to system |
+| app/graphql/types/query_type.rb:37:7:37:28 | call to system |
+| app/graphql/types/query_type.rb:38:7:38:35 | call to system |
+| app/graphql/types/query_type.rb:43:7:43:27 | call to system |
kernelExecCallExecutions
| CommandExecution.rb:23:1:23:16 | call to exec |
| CommandExecution.rb:24:1:24:19 | call to exec |
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
new file mode 100644
index 00000000000..0749ec0313f
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
@@ -0,0 +1,8 @@
+module Mutations
+ class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ argument_class Types::BaseArgument
+ field_class Types::BaseField
+ input_object_class Types::BaseInputObject
+ object_class Types::BaseObject
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
new file mode 100644
index 00000000000..52f01c3d6eb
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
@@ -0,0 +1,14 @@
+module Mutations
+ class Dummy < BaseMutation
+ argument :something_id, ID, required: false
+
+ def load_something(id)
+ "Something number #{id}"
+ end
+
+ def resolve(something:)
+ system("echo #{something}")
+ { success: true }
+ end
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
new file mode 100644
index 00000000000..a51595c00a7
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
@@ -0,0 +1,4 @@
+module Resolvers
+ class Base < GraphQL::Schema::Resolver
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
new file mode 100644
index 00000000000..1fbc927c816
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
@@ -0,0 +1,15 @@
+module Resolvers
+ class DummyResolver < Resolvers::Base
+ type String, null: false
+ argument :something_id, ID, required: true
+
+ def load_something(id)
+ "Something number #{id}"
+ end
+
+ def resolve(something:)
+ system("echo #{something}")
+ "true"
+ end
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
new file mode 100644
index 00000000000..c1bfdabbfee
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
@@ -0,0 +1,4 @@
+module Types
+ class BaseArgument < GraphQL::Schema::Argument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
new file mode 100644
index 00000000000..7142ef7ddb4
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseField < GraphQL::Schema::Field
+ argument_class Types::BaseArgument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
new file mode 100644
index 00000000000..c97c4796373
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseInputObject < GraphQL::Schema::InputObject
+ argument_class Types::BaseArgument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
new file mode 100644
index 00000000000..f25c9650044
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
@@ -0,0 +1,7 @@
+module Types
+ module BaseInterface
+ include GraphQL::Schema::Interface
+
+ field_class Types::BaseField
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
new file mode 100644
index 00000000000..1f918414d98
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseObject < GraphQL::Schema::Object
+ field_class Types::BaseField
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
new file mode 100644
index 00000000000..5ef19f95ae6
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
@@ -0,0 +1,5 @@
+module Types
+ class MutationType < Types::BaseObject
+ field :dummy, mutation: Mutations::Dummy
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
new file mode 100644
index 00000000000..e0bc578a911
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
@@ -0,0 +1,46 @@
+module Types
+ class QueryType < Types::BaseObject
+ field :test_field, String, null: false,
+ description: "An example field added by the generator",
+ resolver: Resolvers::DummyResolver
+
+ field :with_arg, String, null: false, description: "A field with an argument" do
+ argument :number, Int, "A number", required: true
+ end
+ def with_arg(number:)
+ system("echo #{number}")
+ number.to_s
+ end
+
+ field :with_method, String, null: false, description: "A field with a custom resolver method", resolver_method: :custom_method do
+ argument :blah_number, Int, "A number", required: true
+ end
+ def custom_method(blah_number:, number: nil)
+ system("echo #{blah_number}")
+ system("echo #{number}")
+ blah_number.to_s
+ end
+
+ field :with_splat, String, null: false, description: "A field with a double-splatted argument" do
+ argument :something, Int, "A number", required: true
+ end
+ def with_splat(**args)
+ system("echo #{args[:something]}")
+ args[:something].to_s
+ end
+
+ field :with_splat_and_named_arg, String, null: false, description: "A field with two named arguments, where the method captures the second via a hash splat param" do
+ argument :arg1, Int, "A number", required: true
+ argument :arg2, Int, "Another number", required: true
+ end
+ def with_splat_and_named_arg(arg1:, **rest)
+ system("echo #{arg1}")
+ system("echo #{rest[:arg2]}")
+ arg1.to_s
+ end
+
+ def foo(arg)
+ system("echo #{arg}")
+ end
+ end
+end
diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
index 8849322976c..6118b4b20c6 100644
--- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
+++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
@@ -10,6 +10,8 @@ edges
| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:34:39:34:51 | "grep #{...}" |
| CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:46:15:46:26 | ...[...] : |
| CommandInjection.rb:46:15:46:26 | ...[...] : | CommandInjection.rb:50:24:50:36 | "echo #{...}" |
+| CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" |
+| CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" |
nodes
| CommandInjection.rb:6:15:6:20 | call to params : | semmle.label | call to params : |
| CommandInjection.rb:6:15:6:26 | ...[...] : | semmle.label | ...[...] : |
@@ -24,6 +26,10 @@ nodes
| CommandInjection.rb:46:15:46:20 | call to params : | semmle.label | call to params : |
| CommandInjection.rb:46:15:46:26 | ...[...] : | semmle.label | ...[...] : |
| CommandInjection.rb:50:24:50:36 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:64:18:64:23 | number : | semmle.label | number : |
+| CommandInjection.rb:65:14:65:29 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:72:23:72:33 | blah_number : | semmle.label | blah_number : |
+| CommandInjection.rb:73:14:73:34 | "echo #{...}" | semmle.label | "echo #{...}" |
subpaths
#select
| CommandInjection.rb:7:10:7:15 | #{...} | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:7:10:7:15 | #{...} | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
@@ -35,3 +41,5 @@ subpaths
| CommandInjection.rb:33:24:33:36 | "echo #{...}" | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:33:24:33:36 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
| CommandInjection.rb:34:39:34:51 | "grep #{...}" | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:34:39:34:51 | "grep #{...}" | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
| CommandInjection.rb:50:24:50:36 | "echo #{...}" | CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:50:24:50:36 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:46:15:46:20 | call to params | a user-provided value |
+| CommandInjection.rb:65:14:65:29 | "echo #{...}" | CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:64:18:64:23 | number | a user-provided value |
+| CommandInjection.rb:73:14:73:34 | "echo #{...}" | CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:72:23:72:33 | blah_number | a user-provided value |
diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
index f91d36f71bd..ed9750128cc 100644
--- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
+++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
@@ -50,3 +50,41 @@ EOF
Open3.capture2("echo #{cmd}")
end
end
+
+module Types
+ class BaseObject < GraphQL::Schema::Object; end
+ class QueryType < BaseObject
+ field :test_field, String, null: false,
+ description: "An example field added by the generator",
+ resolver: Resolvers::DummyResolver
+
+ field :with_arg, String, null: false, description: "A field with an argument" do
+ argument :number, Int, "A number", required: true
+ end
+ def with_arg(number:)
+ system("echo #{number}")
+ number.to_s
+ end
+
+ field :with_method, String, null: false, description: "A field with a custom resolver method", resolver_method: :custom_method do
+ argument :blah_number, Int, "A number", required: true
+ end
+ def custom_method(blah_number:, number: nil)
+ system("echo #{blah_number}")
+ system("echo #{number}") # OK, number: is not an `argument` for this field
+ blah_number.to_s
+ end
+
+ field :with_splat, String, null: false, description: "A field with a double-splatted argument" do
+ argument :something, Int, "A number", required: true
+ end
+ def with_splat(**args)
+ system("echo #{args[:something]}")
+ args[:something].to_s
+ end
+
+ def foo(arg)
+ system("echo #{arg}") # OK, this is just a random method, not a resolver method
+ end
+ end
+end
From 982fb8f73a185c6c6e269b238cc1036a2ca5ba8d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 18 Jan 2022 16:26:28 +0000
Subject: [PATCH 070/296] C++: Add change note.
---
.../src/change-notes/2022-01-18-improper-null-termination.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
diff --git a/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
new file mode 100644
index 00000000000..19d5b950037
--- /dev/null
+++ b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.
From a3d65a8ed0663b044f6c9d9828cc3f60db5395c9 Mon Sep 17 00:00:00 2001
From: luchua-bc
Date: Tue, 18 Jan 2022 17:01:26 +0000
Subject: [PATCH 071/296] Update recommendation in qldoc and make examples more
comprehendible
---
.../CWE/CWE-552/UnsafeRequestPath.java | 30 ---------
.../CWE-552/UnsafeServletRequestDispatch.java | 64 +++----------------
.../CWE/CWE-552/UnsafeUrlForward.qhelp | 6 +-
3 files changed, 13 insertions(+), 87 deletions(-)
delete mode 100644 java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
deleted file mode 100644
index ffa0ddf63bd..00000000000
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeRequestPath.java
+++ /dev/null
@@ -1,30 +0,0 @@
-public class UnsafeRequestPath implements Filter {
- private static final String BASE_PATH = "/pages";
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-
- {
- // BAD: Request dispatcher from servlet path without check
- String path = ((HttpServletRequest) request).getServletPath();
- // A sample payload "/%57EB-INF/web.xml" can bypass this `startsWith` check
- if (path != null && !path.startsWith("/WEB-INF")) {
- request.getRequestDispatcher(path).forward(request, response);
- } else {
- chain.doFilter(request, response);
- }
- }
-
- {
- // GOOD: Request dispatcher from servlet path with path traversal check
- String path = ((HttpServletRequest) request).getServletPath();
-
- if (path.startsWith(BASE_PATH) && !path.contains("..")) {
- request.getRequestDispatcher(path).forward(request, response);
- } else {
- chain.doFilter(request, response);
- }
- }
- }
-}
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
index 59458912f24..88a794ab9c6 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeServletRequestDispatch.java
@@ -1,55 +1,11 @@
-public class UnsafeServletRequestDispatch extends HttpServlet {
- private static final String BASE_PATH = "/pages";
+// BAD: no URI validation
+String returnURL = request.getParameter("returnURL");
+RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
+rd.forward(request, response);
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- {
- ServletConfig cfg = getServletConfig();
- ServletContext sc = cfg.getServletContext();
-
- // GOOD: check for an explicitly permitted URI
- String action = request.getParameter("action");
- if (action.equals("Login")) {
- RequestDispatcher rd = sc.getRequestDispatcher("/Login.jsp");
- rd.forward(request, response);
- }
-
- // BAD: no URI validation
- String returnURL = request.getParameter("returnURL");
- RequestDispatcher rd = sc.getRequestDispatcher(returnURL);
- rd.forward(request, response);
-
- // A sample payload "/pages/welcome.jsp/../WEB-INF/web.xml" can bypass the `startsWith` check
- // The payload "/pages/welcome.jsp/../../%57EB-INF/web.xml" can bypass the check as well since RequestDispatcher will decode `%57` as `W`
- String path = request.getParameter("path");
-
- // BAD: no check for path traversal
- if (path.startsWith(BASE_PATH)) {
- request.getServletContext().getRequestDispatcher(path).include(request, response);
- }
-
- // GOOD: To check there won't be unexpected path traversal, we can check for any `..` sequences and whether the URI starts with a given web root path.
- if (path.startsWith(BASE_PATH) && !path.contains("..")) {
- request.getServletContext().getRequestDispatcher(path).include(request, response);
- }
-
- // GOOD: Or alternatively we can use Path.normalize and check whether the URI starts with a given web root path.
- Path requestedPath = Paths.get(BASE_PATH).resolve(path).normalize();
- if (requestedPath.startsWith(BASE_PATH)) {
- request.getServletContext().getRequestDispatcher(requestedPath.toString()).forward(request, response);
- }
-
- // GOOD: Or alternatively ensure URL encoding is removed and then check for any `..` sequences.
- boolean hasEncoding = path.contains("%");
- while (hasEncoding) {
- path = URLDecoder.decode(path, "UTF-8");
- hasEncoding = path.contains("%");
- }
-
- if (!path.startsWith("/WEB-INF/") && !path.contains("..")) {
- request.getServletContext().getRequestDispatcher(path).include(request, response);
- }
- }
- }
-}
+// GOOD: check for a trusted prefix, ensuring path traversal is not used to erase that prefix:
+// (alternatively use `Path.normalize` instead of checking for `..`)
+if (!returnURL.contains("..") && returnURL.hasPrefix("/pages")) { ... }
+// Also GOOD: check for a forbidden prefix, ensuring URL-encoding is not used to evade the check:
+// (alternatively use `URLDecoder.decode` before `hasPrefix`)
+if (returnURL.hasPrefix("/internal") && !returnURL.contains("%")) { ... }
\ No newline at end of file
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
index 5b1022d50ee..1ccfaf5078c 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
@@ -13,9 +13,9 @@
Unsanitized user provided data must not be used to construct the path for URL forwarding. In order to prevent
untrusted URL forwarding, it is recommended to avoid concatenating user input directly into the forwarding URL.
-Instead, user input should be checked for path traversal using .. sequences or the user input should
-be normalized using Path.normalize, any URL encoding should be removed, and user input should be
-checked against a permitted URI.
+Instead, user input should be checked against allowed (e.g., must come within user_content/) or disallowed
+(e.g. must not come within /internal) paths, ensuring that neither path traversal using ../
+or URL encoding are used to evade these checks.
From 748008ad517be80dfff4de9a867b7d9e181a19ae Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Tue, 18 Jan 2022 17:08:38 +0000
Subject: [PATCH 072/296] Remove dangling reference to UnsafeRequestPath.java
---
.../src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp | 1 -
1 file changed, 1 deletion(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
index 1ccfaf5078c..345eca1e5d4 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qhelp
@@ -35,7 +35,6 @@ attacks. It also shows how to remedy the problem by validating the user input.
-
From d744cf9053442a1067162ff75bef8028b686f270 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Tue, 18 Jan 2022 12:28:11 +0000
Subject: [PATCH 073/296] Clean up guard logic:
* Always sanitize after the second guard, not the first
* Only check basic-block dominance in one place
* One BarrierGuard extension per final guard
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 111 +++++++++++-------
1 file changed, 69 insertions(+), 42 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index c245b7ffb0a..785813a0d01 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -74,68 +74,99 @@ private class ExactStringPathMatchGuard extends UnsafeUrlForwardBarrierGuard ins
}
}
-/**
- * A guard that considers safe a string being matched against an allowlist of partial trusted values.
- * This requires additional protection against path traversal, either another guard (`PathTraversalGuard`)
- * or a sanitizer (`PathNormalizeSanitizer`).
- */
-private class AllowListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
- AllowListCheckGuard() {
- (isStringPartialMatch(this) or isPathPartialMatch(this)) and
- not isDisallowedWord(this.getAnArgument())
+private class AllowListGuard extends Guard instanceof MethodAccess {
+ AllowListGuard() {
+ (isStringPartialMatch(this.(MethodAccess)) or isPathPartialMatch(this.(MethodAccess))) and
+ not isDisallowedWord(this.(MethodAccess).getAnArgument())
}
+ Expr getCheckedExpr() { result = super.getQualifier() }
+}
+
+/**
+ * A guard that considers a path safe because it is checked against an allowlist of partial trusted values.
+ * This requires additional protection against path traversal, either another guard (`PathTraversalGuard`)
+ * or a sanitizer (`PathNormalizeSanitizer`), to ensure any internal `..` components are removed from the path.
+ */
+private class AllowListBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof AllowListGuard {
override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and
+ e = super.getCheckedExpr() and
branch = true and
(
- // Either the path normalization sanitizer comes before the guard
+ // Either a path normalization sanitizer comes before the guard,
exists(PathNormalizeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
- // or the path traversal check comes before the guard
- exists(PathTraversalGuard guard |
- guard.checks(any(Expr checked | DataFlow::localExprFlow(checked, e))) or
- // or both checks are in the same condition
- // (for example, `path.startsWith(BASE_PATH) && !path.contains("..")`)
- guard.controls(this.getBasicBlock().(ConditionBlock), false) or
- this.controls(guard.getBasicBlock().(ConditionBlock), branch)
+ // or a check like `!path.contains("..")` comes before the guard
+ exists(PathTraversalGuard previousGuard |
+ DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
+ previousGuard.controls(this.getBasicBlock().(ConditionBlock), false)
)
)
}
}
/**
- * A guard that considers safe a string being matched against a blocklist of known dangerous values.
- * This requires additional protection against path traversal, either another guard (`UrlEncodingGuard`)
- * or a sanitizer (`UrlDecodeSanitizer`).
+ * A guard that considers a path safe because it is checked for `..` components, having previously
+ * been checked for a trusted prefix.
*/
-private class BlockListCheckGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
- BlockListCheckGuard() {
+private class DotDotCheckBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof PathTraversalGuard {
+ override predicate checks(Expr e, boolean branch) {
+ e = super.getCheckedExpr() and
+ branch = false and
+ // The same value has previously been checked against a list of allowed prefixes:
+ exists(AllowListGuard previousGuard |
+ DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
+ previousGuard.controls(this.getBasicBlock().(ConditionBlock), true)
+ )
+ }
+}
+
+private class BlockListGuard extends Guard instanceof MethodAccess {
+ BlockListGuard() {
(isStringPartialMatch(this) or isPathPartialMatch(this)) and
isDisallowedWord(this.getAnArgument())
}
+ Expr getCheckedExpr() { result = super.getQualifier() }
+}
+
+/**
+ * A guard that considers a string safe because it is checked against a blocklist of known dangerous values.
+ * This requires a prior check for URL encoding concealing a forbidden value, either a guard (`UrlEncodingGuard`)
+ * or a sanitizer (`UrlDecodeSanitizer`).
+ */
+private class BlockListBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof BlockListGuard {
override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and
+ e = super.getCheckedExpr() and
branch = false and
(
- // Either the URL decode sanitization comes before the guard
+ // Either `e` has been URL decoded:
exists(UrlDecodeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
- // or the URL encoding check comes before the guard
- exists(UrlEncodingGuard guard |
- guard.checks(any(Expr checked | DataFlow::localExprFlow(checked, e)))
- or
- // or both checks are in the same condition
- // (for example, `!path.contains("..") && !path.contains("%")`)
- guard.controls(this.getBasicBlock().(ConditionBlock), false)
- or
- this.controls(guard.getBasicBlock().(ConditionBlock), branch)
+ // or `e` has previously been checked for URL encoding sequences:
+ exists(UrlEncodingGuard previousGuard |
+ DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
+ previousGuard.controls(this.getBasicBlock(), false)
)
)
}
}
+/**
+ * A guard that considers a string safe because it is checked for URL encoding sequences,
+ * having previously been checked against a block-list of forbidden values.
+ */
+private class URLEncodingBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof UrlEncodingGuard {
+ override predicate checks(Expr e, boolean branch) {
+ e = super.getCheckedExpr() and
+ branch = false and
+ exists(BlockListGuard previousGuard |
+ DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
+ previousGuard.controls(this.getBasicBlock(), false)
+ )
+ }
+}
+
/**
* Holds if `ma` is a call to a method that checks a partial string match.
*/
@@ -164,11 +195,10 @@ private class PathTraversalGuard extends Guard instanceof MethodAccess {
PathTraversalGuard() {
this.getMethod().getDeclaringType() instanceof TypeString and
this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".." and
- this.controls(checked.getBasicBlock(), false)
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
}
- predicate checks(Expr e) { checked = e }
+ Expr getCheckedExpr() { result = super.getQualifier() }
}
/** A complementary sanitizer that protects against path traversal using path normalization. */
@@ -181,16 +211,13 @@ private class PathNormalizeSanitizer extends MethodAccess {
/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
private class UrlEncodingGuard extends Guard instanceof MethodAccess {
- Expr checked;
-
UrlEncodingGuard() {
this.getMethod().getDeclaringType() instanceof TypeString and
this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%" and
- this.controls(checked.getBasicBlock(), false)
+ this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
}
- predicate checks(Expr e) { checked = e }
+ Expr getCheckedExpr() { result = super.getQualifier() }
}
/** A complementary sanitizer that protects against double URL encoding using URL decoding. */
From 8eb674358628135c58692131a5db9e771bdabccf Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:22:21 +0100
Subject: [PATCH 074/296] Split out Lang2 rows
---
.../code/java/frameworks/apache/Lang.qll | 273 +-------------
.../java/frameworks/apache/Lang2Generated.qll | 336 ++++++++++++++++++
2 files changed, 337 insertions(+), 272 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
index 45157b4993e..a2dad559bad 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
@@ -1,6 +1,7 @@
/** Definitions related to the Apache Commons Lang library. */
import java
+import Lang2Generated
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.ExternalFlow
@@ -311,155 +312,6 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
]
}
}
@@ -494,58 +346,6 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
]
}
}
@@ -578,20 +378,6 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
]
}
}
@@ -617,34 +403,6 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
]
}
}
@@ -658,8 +416,6 @@ private class ApacheStrLookupModel extends SummaryModelCsv {
[
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
]
}
}
@@ -698,33 +454,6 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
]
}
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
new file mode 100644
index 00000000000..f83a07b4985
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -0,0 +1,336 @@
+/** Definitions related to the Apache Commons Lang 2 library. */
+
+import java
+private import semmle.code.java.dataflow.ExternalFlow
+
+private class ApacheStrBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `WordUtils`.
+ */
+private class ApacheWordUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrTokenizer`.
+ */
+private class ApacheStrTokenizerModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrLookup`.
+ */
+private class ApacheStrLookupModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrSubstitutor`.
+ */
+private class ApacheStrSubstitutorModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
+ ]
+ }
+}
From 82bda6d573f2de74528e343d82b6a25afce9715f Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:23:37 +0100
Subject: [PATCH 075/296] Merge Lang2 summary models
---
.../java/frameworks/apache/Lang2Generated.qll | 64 ++-----------------
1 file changed, 6 insertions(+), 58 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
index f83a07b4985..dff115e676c 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -3,7 +3,7 @@
import java
private import semmle.code.java.dataflow.ExternalFlow
-private class ApacheStrBuilderModel extends SummaryModelCsv {
+private class ApacheCommonsLangModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
@@ -155,15 +155,7 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
@@ -215,18 +207,7 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
@@ -240,18 +221,7 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
@@ -279,31 +249,9 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint",
"org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
From 67b60dcf78573a390a10df1797077fdddcd55541 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:24:12 +0100
Subject: [PATCH 076/296] Sort Lang2 rows
---
.../java/frameworks/apache/Lang2Generated.qll | 344 +++++++++---------
1 file changed, 172 insertions(+), 172 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
index dff115e676c..757f28f19cf 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -7,278 +7,278 @@ private class ApacheCommonsLangModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
- "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
"org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
"org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
]
}
}
From 736e68820c1cc036b38ae5625078743ff0182887 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:26:34 +0100
Subject: [PATCH 077/296] Split out Lang3 models
---
.../code/java/frameworks/apache/Lang.qll | 578 +----------------
.../java/frameworks/apache/Lang3Generated.qll | 581 ++++++++++++++++++
2 files changed, 582 insertions(+), 577 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
index a2dad559bad..b536539670e 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
@@ -2,6 +2,7 @@
import java
import Lang2Generated
+import Lang3Generated
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.ExternalFlow
@@ -28,328 +29,6 @@ class MethodApacheSerializationUtilsDeserialize extends Method {
}
}
-/**
- * Taint-propagating models for `ArrayUtils`.
- */
-private class ApacheArrayUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
- ]
- }
-}
-
-private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStringUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- ]
- }
-}
-
/**
* An Apache Commons-Lang StrBuilder method that returns `this`.
*/
@@ -358,258 +37,3 @@ private class ApacheStrBuilderFluentMethod extends FluentMethod {
this.getReturnType().(RefType).hasQualifiedName("org.apache.commons.lang3.text", "StrBuilder")
}
}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `RegexUtils`.
- */
-private class ApacheRegExUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `ObjectUtils`.
- */
-private class ApacheObjectUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- // Note all the functions annotated with `taint` flow really should have `value` flow,
- // but we don't support value-preserving varargs functions at the moment.
- "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
- ]
- }
-}
-
-private class ApacheToStringBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- // The following are value-preserving steps for fluent methods:
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
- */
-private class ApachePairModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
- */
-private class ApacheTripleModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `MutableObject`.
- */
-private class ApacheMutableObjectModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
- ]
- }
-}
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
new file mode 100644
index 00000000000..1513898adf8
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -0,0 +1,581 @@
+/** Definitions related to the Apache Commons Lang 3 library. */
+
+import java
+private import semmle.code.java.dataflow.ExternalFlow
+
+/**
+ * Taint-propagating models for `ArrayUtils`.
+ */
+private class ApacheArrayUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
+ ]
+ }
+}
+
+private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStringUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStrBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
+ ]
+ }
+}
+
+private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `WordUtils`.
+ */
+private class ApacheWordUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrTokenizer`.
+ */
+private class ApacheStrTokenizerModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrLookup`.
+ */
+private class ApacheStrLookupModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrSubstitutor`.
+ */
+private class ApacheStrSubstitutorModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `RegexUtils`.
+ */
+private class ApacheRegExUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `ObjectUtils`.
+ */
+private class ApacheObjectUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ // Note all the functions annotated with `taint` flow really should have `value` flow,
+ // but we don't support value-preserving varargs functions at the moment.
+ "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
+ ]
+ }
+}
+
+private class ApacheToStringBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
+ // The following are value-preserving steps for fluent methods:
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
+ */
+private class ApachePairModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
+ */
+private class ApacheTripleModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `MutableObject`.
+ */
+private class ApacheMutableObjectModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
+ ]
+ }
+}
From e6800c877c4f856a14ac73e0c9b40a5581cdceb2 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:28:55 +0100
Subject: [PATCH 078/296] Merge Lang3 rows
---
.../java/frameworks/apache/Lang3Generated.qll | 163 +-----------------
1 file changed, 9 insertions(+), 154 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
index 1513898adf8..43c1da32177 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -3,10 +3,7 @@
import java
private import semmle.code.java.dataflow.ExternalFlow
-/**
- * Taint-propagating models for `ArrayUtils`.
- */
-private class ApacheArrayUtilsModel extends SummaryModelCsv {
+private class ApacheCommonsLang3Model extends SummaryModelCsv {
override predicate row(string row) {
row =
[
@@ -44,24 +41,8 @@ private class ApacheArrayUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
- ]
- }
-}
-
-private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStringUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
@@ -204,15 +185,7 @@ private class ApacheStringUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
@@ -287,14 +260,6 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
@@ -321,17 +286,6 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
@@ -344,17 +298,6 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
@@ -369,30 +312,8 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
@@ -420,17 +341,6 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `RegexUtils`.
- */
-private class ApacheRegExUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
@@ -439,20 +349,7 @@ private class ApacheRegExUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `ObjectUtils`.
- */
-private class ApacheObjectUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- // Note all the functions annotated with `taint` flow really should have `value` flow,
- // but we don't support value-preserving varargs functions at the moment.
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
@@ -466,15 +363,7 @@ private class ApacheObjectUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
- ]
- }
-}
-
-private class ApacheToStringBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
@@ -488,22 +377,10 @@ private class ApacheToStringBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- // The following are value-preserving steps for fluent methods:
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
- */
-private class ApachePairModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
@@ -526,18 +403,7 @@ private class ApachePairModel extends SummaryModelCsv {
"org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
- */
-private class ApacheTripleModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
@@ -561,18 +427,7 @@ private class ApacheTripleModel extends SummaryModelCsv {
"org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `MutableObject`.
- */
-private class ApacheMutableObjectModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value",
"org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
"org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
"org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
From 9e91b805d6ce2e9a82d3c2d9681d0686492c9041 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:29:26 +0100
Subject: [PATCH 079/296] Sort Lang3 models
---
.../java/frameworks/apache/Lang3Generated.qll | 394 +++++++++---------
1 file changed, 197 insertions(+), 197 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
index 43c1da32177..251f72e4c80 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -7,23 +7,23 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
override predicate row(string row) {
row =
[
- "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
@@ -35,17 +35,40 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
+ "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
@@ -53,10 +76,10 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
@@ -70,31 +93,31 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
@@ -112,14 +135,14 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
@@ -137,23 +160,23 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
@@ -179,258 +202,235 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
"org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
]
}
}
From 1e32514600132eb40d7a5c9944efb0ff926992c6 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Tue, 18 Jan 2022 17:20:40 +0000
Subject: [PATCH 080/296] Avoid using `this` for a non-extending supertype, and
remove needless casts
---
.../Security/CWE/CWE-552/UnsafeUrlForward.qll | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
index 785813a0d01..5c07b67f43d 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
+++ b/java/ql/src/experimental/Security/CWE/CWE-552/UnsafeUrlForward.qll
@@ -64,20 +64,20 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
*/
private class ExactStringPathMatchGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
ExactStringPathMatchGuard() {
- this.getMethod().getDeclaringType() instanceof TypeString and
- this.getMethod().getName() = ["equals", "equalsIgnoreCase"]
+ super.getMethod().getDeclaringType() instanceof TypeString and
+ super.getMethod().getName() = ["equals", "equalsIgnoreCase"]
}
override predicate checks(Expr e, boolean branch) {
- e = this.(MethodAccess).getQualifier() and
+ e = super.getQualifier() and
branch = true
}
}
private class AllowListGuard extends Guard instanceof MethodAccess {
AllowListGuard() {
- (isStringPartialMatch(this.(MethodAccess)) or isPathPartialMatch(this.(MethodAccess))) and
- not isDisallowedWord(this.(MethodAccess).getAnArgument())
+ (isStringPartialMatch(this) or isPathPartialMatch(this)) and
+ not isDisallowedWord(super.getAnArgument())
}
Expr getCheckedExpr() { result = super.getQualifier() }
@@ -124,7 +124,7 @@ private class DotDotCheckBarrierGuard extends UnsafeUrlForwardBarrierGuard insta
private class BlockListGuard extends Guard instanceof MethodAccess {
BlockListGuard() {
(isStringPartialMatch(this) or isPathPartialMatch(this)) and
- isDisallowedWord(this.getAnArgument())
+ isDisallowedWord(super.getAnArgument())
}
Expr getCheckedExpr() { result = super.getQualifier() }
@@ -193,9 +193,9 @@ private class PathTraversalGuard extends Guard instanceof MethodAccess {
Expr checked;
PathTraversalGuard() {
- this.getMethod().getDeclaringType() instanceof TypeString and
- this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
+ super.getMethod().getDeclaringType() instanceof TypeString and
+ super.getMethod().hasName(["contains", "indexOf"]) and
+ super.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
}
Expr getCheckedExpr() { result = super.getQualifier() }
@@ -212,9 +212,9 @@ private class PathNormalizeSanitizer extends MethodAccess {
/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
private class UrlEncodingGuard extends Guard instanceof MethodAccess {
UrlEncodingGuard() {
- this.getMethod().getDeclaringType() instanceof TypeString and
- this.getMethod().hasName(["contains", "indexOf"]) and
- this.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
+ super.getMethod().getDeclaringType() instanceof TypeString and
+ super.getMethod().hasName(["contains", "indexOf"]) and
+ super.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
}
Expr getCheckedExpr() { result = super.getQualifier() }
From d1c89562b832b309f6fcb034e1bae9e0d0266fb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 21:45:13 +0100
Subject: [PATCH 081/296] Apply suggestions from code review
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 9c0481702f7..a06e63d0925 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -55,10 +55,11 @@ where
) and
(
fctmp.getArgument(1).getValue().matches("%a%") or
+ fctmp.getArgument(1).getValue().matches("%w%") or
// unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
- fctmp.getArgument(1).getValueText().matches("%O_APPEND%")
+ fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
From 3fa25168984cddda7b7313b3164b843520cb5b87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 21:47:55 +0100
Subject: [PATCH 082/296] Update
cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index a06e63d0925..43344b589ad 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -56,7 +56,7 @@ where
(
fctmp.getArgument(1).getValue().matches("%a%") or
fctmp.getArgument(1).getValue().matches("%w%") or
- // unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
+ // unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
From 4f7f92490a4afb01c5b3b163d5664b08feb2dbea Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 18 Jan 2022 15:02:13 +1300
Subject: [PATCH 083/296] Distinguish regex components from strings
Create a set of classes for components of regex literals,
separate from those of string literals. This allows us to special-case
components of free-spacing regexes (ones with the /x flag) to not have a
`getValueText()`.
This in turn is useful because our regex parser can't handle free-spacing
regexes, so excluding them ensures that we don't generate erroneous
ReDoS alerts.
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 88 ++++++++++++++++++-
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 34 ++++++-
.../internal/ControlFlowGraphImpl.qll | 8 +-
ruby/ql/test/library-tests/ast/Ast.expected | 62 ++++++-------
.../test/library-tests/ast/ValueText.expected | 2 -
.../ast/literals/literals.expected | 73 +++++++--------
.../library-tests/ast/literals/literals.ql | 4 +
7 files changed, 193 insertions(+), 78 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 1f5350bdb33..177b771c73c 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -277,7 +277,9 @@ class StringComponent extends AstNode, TStringComponent {
class StringTextComponent extends StringComponent, TStringTextComponent {
private Ruby::Token g;
- StringTextComponent() { this = TStringTextComponent(g) }
+ StringTextComponent() {
+ this = TStringTextComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = g.getValue() }
@@ -292,7 +294,9 @@ class StringTextComponent extends StringComponent, TStringTextComponent {
class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
private Ruby::EscapeSequence g;
- StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+ StringEscapeSequenceComponent() {
+ this = TStringEscapeSequenceComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = g.getValue() }
@@ -308,7 +312,9 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
TStringInterpolationComponent {
private Ruby::Interpolation g;
- StringInterpolationComponent() { this = TStringInterpolationComponent(g) }
+ StringInterpolationComponent() {
+ this = TStringInterpolationComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = "#{...}" }
@@ -319,6 +325,82 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
+/**
+ * The base class for a component of a regular expression literal.
+ */
+class RegExpComponent extends AstNode, TStringComponent {
+ private RegExpLiteral parent;
+
+ RegExpComponent() { toGenerated(this).getParent() = toGenerated(parent) }
+
+ string getValueText() { none() }
+}
+
+/**
+ * A component of a regex literal that is simply text.
+ *
+ * For example, the following regex literals all contain `RegExpTextComponent`
+ * components whose `getValueText()` returns `"foo"`:
+ *
+ * ```rb
+ * 'foo'
+ * "#{ bar() }foo"
+ * "foo#{ bar() } baz"
+ * ```
+ */
+class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
+ private Ruby::Token g;
+
+ RegExpTextComponent() { this = TStringTextComponent(g) and g.getParent() instanceof Ruby::Regex }
+
+ final override string toString() { result = g.getValue() }
+
+ // Exclude components that are children of a free-spacing regex.
+ // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
+ final override string getValueText() {
+ not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
+ }
+
+ final override string getAPrimaryQlClass() { result = "RegExpTextComponent" }
+}
+
+/**
+ * An escape sequence component of a regex literal.
+ */
+class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponent {
+ private Ruby::EscapeSequence g;
+
+ RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+
+ final override string toString() { result = g.getValue() }
+
+ // Exclude components that are children of a free-spacing regex.
+ // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
+ final override string getValueText() {
+ not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
+ }
+
+ final override string getAPrimaryQlClass() { result = "RegExpEscapeSequenceComponent" }
+}
+
+/**
+ * An interpolation expression component of a regex literal.
+ */
+class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
+ TStringInterpolationComponent {
+ private Ruby::Interpolation g;
+
+ RegExpInterpolationComponent() { this = TStringInterpolationComponent(g) }
+
+ final override string toString() { result = "#{...}" }
+
+ final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
+
+ final override string getValueText() { none() }
+
+ final override string getAPrimaryQlClass() { result = "RegExpInterpolationComponent" }
+}
+
/**
* A string, symbol, regexp, or subshell literal.
*/
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 8c35c4fc1b0..36eb0b3078f 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -132,6 +132,13 @@ class StringComponentCfgNode extends AstCfgNode {
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
+/** A control-flow node that wraps a `RegExpComponent` AST expression. */
+class RegExpComponentCfgNode extends AstCfgNode {
+ RegExpComponentCfgNode() { this.getNode() instanceof RegExpComponent }
+
+ string getValueText() { result = this.getNode().(RegExpComponent).getValueText() }
+}
+
private AstNode desugar(AstNode n) {
result = n.getDesugared()
or
@@ -474,6 +481,15 @@ module ExprNodes {
final override string getValueText() { result = this.getLastStmt().getValueText() }
}
+ /** A control-flow node that wraps a `RegExpInterpolationComponent` AST expression. */
+ class RegExpInterpolationComponentCfgNode extends RegExpComponentCfgNode, StmtSequenceCfgNode {
+ RegExpInterpolationComponentCfgNode() { this.getNode() instanceof RegExpInterpolationComponent }
+
+ // If last statement in the interpolation is a constant or local variable read,
+ // attempt to look up its definition and return the definition's `getValueText()`.
+ final override string getValueText() { result = this.getLastStmt().getValueText() }
+ }
+
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
@@ -510,11 +526,27 @@ module ExprNodes {
final override StringLiteral getExpr() { result = super.getExpr() }
}
+ private class RegExpLiteralChildMapping extends ExprChildMapping, RegExpLiteral {
+ override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
+ }
+
/** A control-flow node that wraps a `RegExpLiteral` AST expression. */
class RegExpLiteralCfgNode extends ExprCfgNode {
- override RegExpLiteral e;
+ override RegExpLiteralChildMapping e;
+
+ RegExpComponentCfgNode getComponent(int n) { e.hasCfgChild(e.getComponent(n), this, result) }
final override RegExpLiteral getExpr() { result = super.getExpr() }
+
+ language[monotonicAggregates]
+ override string getValueText() {
+ result =
+ concat(RegExpComponentCfgNode c, int i |
+ c = this.getComponent(i)
+ |
+ c.getValueText() order by i
+ )
+ }
}
/** A control-flow node that wraps a `ComparisonOperation` AST expression. */
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index c56d1e6369d..99e6b86dd21 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1351,7 +1351,13 @@ module Trees {
}
private class StringComponentTree extends LeafTree, StringComponent {
- StringComponentTree() { not this instanceof StringInterpolationComponent }
+ StringComponentTree() {
+ // Interpolations contain `StmtSequence`s, so they shouldn't be treated as leaf nodes.
+ not this instanceof StringInterpolationComponent and
+ // In the interests of brevity we treat regexes as string literals when constructing the CFG.
+ // Thus we must exclude regex interpolations here too.
+ not this instanceof RegExpInterpolationComponent
+ }
}
private class ToplevelTree extends BodyStmtTree, Toplevel {
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 94b5cb5fda1..e48bc0d102f 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -946,7 +946,7 @@ control/cases.rb:
# 92| 0: [RegExpCharacterRange] 0-9
# 92| 0: [RegExpConstant, RegExpNormalChar] 0
# 92| 1: [RegExpConstant, RegExpNormalChar] 9
-# 92| getComponent: [StringTextComponent] .*abc[0-9]
+# 92| getComponent: [RegExpTextComponent] .*abc[0-9]
# 93| getBranch: [InClause] in ... then ...
# 93| getPattern: [RangeLiteral] _ .. _
# 93| getBegin: [IntegerLiteral] 5
@@ -1761,13 +1761,13 @@ literals/literals.rb:
# 137| 0: [RegExpConstant, RegExpNormalChar] f
# 137| 1: [RegExpConstant, RegExpNormalChar] o
# 137| 2: [RegExpConstant, RegExpNormalChar] o
-# 137| getComponent: [StringTextComponent] foo
+# 137| getComponent: [RegExpTextComponent] foo
# 138| getStmt: [RegExpLiteral] /foo/
# 138| getParsed: [RegExpSequence] foo
# 138| 0: [RegExpConstant, RegExpNormalChar] f
# 138| 1: [RegExpConstant, RegExpNormalChar] o
# 138| 2: [RegExpConstant, RegExpNormalChar] o
-# 138| getComponent: [StringTextComponent] foo
+# 138| getComponent: [RegExpTextComponent] foo
# 139| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 139| getParsed: [RegExpSequence] foo+\sbar\S
# 139| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1779,10 +1779,10 @@ literals/literals.rb:
# 139| 5: [RegExpConstant, RegExpNormalChar] a
# 139| 6: [RegExpConstant, RegExpNormalChar] r
# 139| 7: [RegExpCharacterClassEscape] \S
-# 139| getComponent: [StringTextComponent] foo+
-# 139| getComponent: [StringEscapeSequenceComponent] \s
-# 139| getComponent: [StringTextComponent] bar
-# 139| getComponent: [StringEscapeSequenceComponent] \S
+# 139| getComponent: [RegExpTextComponent] foo+
+# 139| getComponent: [RegExpEscapeSequenceComponent] \s
+# 139| getComponent: [RegExpTextComponent] bar
+# 139| getComponent: [RegExpEscapeSequenceComponent] \S
# 140| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 140| getParsed: [RegExpSequence] foo2barbarbar
# 140| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1798,35 +1798,31 @@ literals/literals.rb:
# 140| 10: [RegExpConstant, RegExpNormalChar] b
# 140| 11: [RegExpConstant, RegExpNormalChar] a
# 140| 12: [RegExpConstant, RegExpNormalChar] r
-# 140| getComponent: [StringTextComponent] foo
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpTextComponent] foo
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [AddExpr] ... + ...
# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 140| getComponent: [StringTextComponent] bar
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpTextComponent] bar
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [LocalVariableAccess] bar
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [ConstantReadAccess] BAR
# 141| getStmt: [RegExpLiteral] /foo/
-# 141| getParsed: [RegExpSequence] foo
-# 141| 0: [RegExpConstant, RegExpNormalChar] f
-# 141| 1: [RegExpConstant, RegExpNormalChar] o
-# 141| 2: [RegExpConstant, RegExpNormalChar] o
-# 141| getComponent: [StringTextComponent] foo
+# 141| getComponent: [RegExpTextComponent] foo
# 142| getStmt: [RegExpLiteral] //
# 143| getStmt: [RegExpLiteral] /foo/
# 143| getParsed: [RegExpSequence] foo
# 143| 0: [RegExpConstant, RegExpNormalChar] f
# 143| 1: [RegExpConstant, RegExpNormalChar] o
# 143| 2: [RegExpConstant, RegExpNormalChar] o
-# 143| getComponent: [StringTextComponent] foo
+# 143| getComponent: [RegExpTextComponent] foo
# 144| getStmt: [RegExpLiteral] /foo/
# 144| getParsed: [RegExpSequence] foo
# 144| 0: [RegExpConstant, RegExpNormalChar] f
# 144| 1: [RegExpConstant, RegExpNormalChar] o
# 144| 2: [RegExpConstant, RegExpNormalChar] o
-# 144| getComponent: [StringTextComponent] foo
+# 144| getComponent: [RegExpTextComponent] foo
# 145| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 145| getParsed: [RegExpSequence] foo+\sbar\S
# 145| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1838,10 +1834,10 @@ literals/literals.rb:
# 145| 5: [RegExpConstant, RegExpNormalChar] a
# 145| 6: [RegExpConstant, RegExpNormalChar] r
# 145| 7: [RegExpCharacterClassEscape] \S
-# 145| getComponent: [StringTextComponent] foo+
-# 145| getComponent: [StringEscapeSequenceComponent] \s
-# 145| getComponent: [StringTextComponent] bar
-# 145| getComponent: [StringEscapeSequenceComponent] \S
+# 145| getComponent: [RegExpTextComponent] foo+
+# 145| getComponent: [RegExpEscapeSequenceComponent] \s
+# 145| getComponent: [RegExpTextComponent] bar
+# 145| getComponent: [RegExpEscapeSequenceComponent] \S
# 146| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 146| getParsed: [RegExpSequence] foo2barbarbar
# 146| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1857,22 +1853,18 @@ literals/literals.rb:
# 146| 10: [RegExpConstant, RegExpNormalChar] b
# 146| 11: [RegExpConstant, RegExpNormalChar] a
# 146| 12: [RegExpConstant, RegExpNormalChar] r
-# 146| getComponent: [StringTextComponent] foo
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpTextComponent] foo
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [AddExpr] ... + ...
# 146| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 146| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 146| getComponent: [StringTextComponent] bar
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpTextComponent] bar
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [LocalVariableAccess] bar
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [ConstantReadAccess] BAR
# 147| getStmt: [RegExpLiteral] /foo/
-# 147| getParsed: [RegExpSequence] foo
-# 147| 0: [RegExpConstant, RegExpNormalChar] f
-# 147| 1: [RegExpConstant, RegExpNormalChar] o
-# 147| 2: [RegExpConstant, RegExpNormalChar] o
-# 147| getComponent: [StringTextComponent] foo
+# 147| getComponent: [RegExpTextComponent] foo
# 150| getStmt: [StringLiteral] "abcdefghijklmnopqrstuvwxyzabcdef"
# 150| getComponent: [StringTextComponent] abcdefghijklmnopqrstuvwxyzabcdef
# 151| getStmt: [StringLiteral] "foobarfoobarfoobarfoobarfooba..."
@@ -2399,7 +2391,7 @@ operations/operations.rb:
# 65| 2: [RegExpConstant, RegExpNormalChar] o
# 65| 3: [RegExpStar] .*
# 65| 0: [RegExpDot] .
-# 65| getComponent: [StringTextComponent] foo.*
+# 65| getComponent: [RegExpTextComponent] foo.*
# 66| getStmt: [NoRegExpMatchExpr] ... !~ ...
# 66| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] handle
# 66| getAnOperand/getArgument/getRightOperand: [RegExpLiteral] /.*bar/
@@ -2409,7 +2401,7 @@ operations/operations.rb:
# 66| 1: [RegExpConstant, RegExpNormalChar] b
# 66| 2: [RegExpConstant, RegExpNormalChar] a
# 66| 3: [RegExpConstant, RegExpNormalChar] r
-# 66| getComponent: [StringTextComponent] .*bar
+# 66| getComponent: [RegExpTextComponent] .*bar
# 69| getStmt: [AssignAddExpr] ... += ...
# 69| getAnOperand/getLeftOperand: [LocalVariableAccess] x
# 69| getAnOperand/getRightOperand: [IntegerLiteral] 128
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index a456501c0c8..59ca6a262b0 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -552,7 +552,6 @@
| literals/literals.rb:140:12:140:12 | 1 | 1 |
| literals/literals.rb:140:20:140:22 | bar | bar |
| literals/literals.rb:140:26:140:28 | BAR | bar |
-| literals/literals.rb:141:1:141:8 | /foo/ | foo |
| literals/literals.rb:142:1:142:4 | // | |
| literals/literals.rb:143:1:143:7 | /foo/ | foo |
| literals/literals.rb:144:1:144:8 | /foo/ | foo |
@@ -563,7 +562,6 @@
| literals/literals.rb:146:14:146:14 | 1 | 1 |
| literals/literals.rb:146:22:146:24 | bar | bar |
| literals/literals.rb:146:28:146:30 | BAR | bar |
-| literals/literals.rb:147:1:147:10 | /foo/ | foo |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals/literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.expected b/ruby/ql/test/library-tests/ast/literals/literals.expected
index a84d52fe2b0..6c0428650f7 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.expected
+++ b/ruby/ql/test/library-tests/ast/literals/literals.expected
@@ -198,7 +198,7 @@ allLiterals
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | |
| literals.rb:142:1:142:4 | // | RegExpLiteral | |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
@@ -206,7 +206,7 @@ allLiterals
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
-| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -310,13 +310,13 @@ stringlikeLiterals
| literals.rb:138:1:138:6 | /foo/ | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
-| literals.rb:141:1:141:8 | /foo/ | foo |
+| literals.rb:141:1:141:8 | /foo/ | |
| literals.rb:142:1:142:4 | // | |
| literals.rb:143:1:143:7 | /foo/ | foo |
| literals.rb:144:1:144:8 | /foo/ | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
-| literals.rb:147:1:147:10 | /foo/ | foo |
+| literals.rb:147:1:147:10 | /foo/ | |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -387,13 +387,20 @@ regExpLiterals
| literals.rb:138:1:138:6 | /foo/ | foo | i |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
-| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
+| literals.rb:141:1:141:8 | /foo/ | | oxm |
| literals.rb:142:1:142:4 | // | | |
| literals.rb:143:1:143:7 | /foo/ | foo | |
| literals.rb:144:1:144:8 | /foo/ | foo | i |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
-| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
+| literals.rb:147:1:147:10 | /foo/ | | mxo |
+regExpInterpolations
+| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
+| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
+| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
+| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
+| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
+| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
symbolLiterals
| literals.rb:84:1:84:3 | :"" | |
| literals.rb:85:1:85:6 | :hello | hello |
@@ -540,30 +547,30 @@ stringComponents
| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 5 | literals.rb:132:26:132:31 | #{...} | StringInterpolationComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:133:4:133:9 | du -d | StringTextComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:133:10:133:19 | #{...} | StringInterpolationComponent |
-| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
-| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | StringEscapeSequenceComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | StringInterpolationComponent |
-| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | StringTextComponent |
-| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
-| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | StringEscapeSequenceComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | StringInterpolationComponent |
-| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | StringTextComponent |
+| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | RegExpTextComponent |
+| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | RegExpEscapeSequenceComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | RegExpEscapeSequenceComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | RegExpTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | RegExpInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | RegExpTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | RegExpInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | RegExpInterpolationComponent |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | RegExpTextComponent |
+| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | RegExpTextComponent |
+| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | RegExpEscapeSequenceComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | RegExpEscapeSequenceComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | RegExpTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | RegExpInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | RegExpTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | RegExpInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | RegExpInterpolationComponent |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | RegExpTextComponent |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:150:2:150:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:151:2:151:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 0 | literals.rb:152:2:152:7 | foobar | StringTextComponent |
@@ -613,12 +620,6 @@ stringInterpolations
| literals.rb:132:19:132:24 | #{...} | 0 | literals.rb:132:21:132:23 | bar | LocalVariableAccess |
| literals.rb:132:26:132:31 | #{...} | 0 | literals.rb:132:28:132:30 | BAR | ConstantReadAccess |
| literals.rb:133:10:133:19 | #{...} | 0 | literals.rb:133:13:133:17 | ... - ... | SubExpr |
-| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
-| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
-| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
-| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
-| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
-| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
| literals.rb:158:14:158:22 | #{...} | 0 | literals.rb:158:17:158:20 | call to name | MethodCall |
| literals.rb:172:12:172:29 | #{...} | 0 | literals.rb:172:15:172:27 | call to interpolation | MethodCall |
| literals.rb:177:15:177:32 | #{...} | 0 | literals.rb:177:18:177:30 | call to interpolation | MethodCall |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.ql b/ruby/ql/test/library-tests/ast/literals/literals.ql
index 52469a35e50..0fd46abea70 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.ql
+++ b/ruby/ql/test/library-tests/ast/literals/literals.ql
@@ -23,6 +23,10 @@ query predicate regExpLiterals(RegExpLiteral l, string valueText, string flags)
stringlikeLiterals(l, valueText) and flags = l.getFlagString()
}
+query predicate regExpInterpolations(RegExpInterpolationComponent c, int i, Expr e, string eClass) {
+ e = c.getStmt(i) and eClass = e.getAPrimaryQlClass()
+}
+
query predicate symbolLiterals(SymbolLiteral l, string valueText) {
stringlikeLiterals(l, valueText)
}
From 7fcf567edae712ef6f72179a1f6970c1c7aee237 Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Mon, 17 Jan 2022 09:42:42 -0800
Subject: [PATCH 084/296] Docs: Simplify getting started docs
It is no longer necessary to check out a version of `github/codeql` as
a sibling directory to the distribution. Instead, users can download
the required packs as needed. using the `pack download` command or
the `--download` option for `codeql database analyze`.
---
.../getting-started-with-the-codeql-cli.rst | 155 +++++-------------
1 file changed, 42 insertions(+), 113 deletions(-)
diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
index eaf47ec62f3..0063b6bfc3d 100644
--- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
@@ -4,7 +4,7 @@ Getting started with the CodeQL CLI
===================================
To run CodeQL commands, you need to set up the CLI so that it can access
-the tools, queries, and libraries required to create and analyze databases.
+the tools, queries, and libraries required to create and analyze databases.
.. include:: ../reusables/license-note.rst
@@ -18,16 +18,16 @@ structures. To get started quickly, we recommend adopting a relatively simple
setup, as outlined in the steps below.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
-follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
-and 4 are slightly different---for further details, see the sections labeled
+follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
+and 4 are slightly different---for further details, see the sections labeled
**Information for macOS "Catalina" (or newer) users**. If you are using macOS
on Apple Silicon (e.g. Apple M1), ensure that the `Xcode command-line developer
tools `__ and `Rosetta 2
`__ are installed.
For information about installing the CodeQL CLI in a CI system to create results
-to display in GitHub as code scanning alerts, see
-`Installing CodeQL CLI in your CI system `__
+to display in GitHub as code scanning alerts, see
+`Installing CodeQL CLI in your CI system `__
in the GitHub documentation.
1. Download the CodeQL CLI zip package
@@ -42,9 +42,9 @@ Conditions `__.
There are several different versions of the CLI available to download, depending
on your use case:
-
+
- If you want to use the most up to date CodeQL tools and features, download the
- version tagged ``latest``.
+ version tagged ``latest``.
- If you want to create CodeQL databases to upload to LGTM Enterprise, download
the version that is compatible with the relevant LGTM Enterprise version
@@ -53,9 +53,9 @@ Conditions `__.
`__ on GitHub. Using the
correct version of the CLI ensures that your CodeQL databases are
compatible with your version of LGTM Enterprise. For more information,
- see `Preparing CodeQL databases to upload to LGTM
+ see `Preparing CodeQL databases to upload to LGTM
`__
- in the LGTM admin help.
+ in the LGTM admin help.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
`download the zip archive
@@ -72,97 +72,23 @@ Alternatively, you can download ``codeql.zip``, which contains the CLI for all s
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina" (or newer)
-
- If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
- version 12 ("Monterey"), you need to ensure that your web browser does not automatically
- extract zip files. If you use Safari, complete the following steps before downloading
+
+ If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
+ version 12 ("Monterey"), you need to ensure that your web browser does not automatically
+ extract zip files. If you use Safari, complete the following steps before downloading
the CodeQL CLI zip archive:
-
+
i. Open Safari.
ii. From the Safari menu, select **Preferences...**.
iii. Click the **General** Tab.
iv. Ensure the check-box labeled **Open "safe" files after downloading**.
is unchecked.
-2. Create a new CodeQL directory
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Create a new directory where you can place the CLI and any queries and libraries
-you want to use. For example, ``$HOME/codeql-home``.
-
-The CLI's built-in search operations automatically look in all of its sibling
-directories for the files used in database creation and analysis. Keeping these
-components in their own directory prevents the CLI searching unrelated sibling
-directories while ensuring all files are available without specifying any
-further options on the command line.
-
-.. _local-copy-codeql-queries:
-
-3. Obtain a local copy of the CodeQL queries
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The `CodeQL repository `__ contains
-the queries and libraries required for CodeQL analysis of C/C++, C#, Java,
-JavaScript/TypeScript, Python, and Ruby.
-Clone a copy of this repository into ``codeql-home``.
-
-By default, the root of the cloned repository will be called ``codeql``.
-Rename this folder ``codeql-repo`` to avoid conflicting with the CodeQL
-CLI that you will extract in step 4. If you use git on the command line, you can
-clone and rename the repository in a single step by running
-``git clone git@github.com:github/codeql.git codeql-repo`` in the ``codeql-home`` folder.
-
-The CodeQL libraries and queries for Go analysis live in the `CodeQL for Go
-repository `__. Clone a copy of this
-repository into ``codeql-home``.
-
-The cloned repositories should have a sibling relationship.
-For example, if the root of the cloned CodeQL repository is
-``$HOME/codeql-home/codeql-repo``, then the root of the cloned CodeQL for Go
-repository should be ``$HOME/codeql-home/codeql-go``.
-
-Within these repositories, the queries and libraries are organized into QL
-packs. Along with the queries themselves, QL packs contain important metadata
-that tells the CodeQL CLI how to process the query files. For more information,
-see ":doc:`About QL packs `."
-
-.. pull-quote:: Important
-
- There are different versions of the CodeQL queries available for different
- users. Check out the correct version for your use case:
-
- - For the queries used on `LGTM.com `__, check out the
- ``lgtm.com`` branch. You should use this branch for databases you've built
- using the CodeQL CLI, fetched from code scanning on GitHub, or recently downloaded from LGTM.com.
- The queries on the ``lgtm.com`` branch are more likely to be compatible
- with the ``latest`` CLI, so you'll be less likely to have to upgrade
- newly-created databases than if you use the ``main`` branch. Older databases
- may need to be upgraded before you can analyze them.
-
- - For the most up to date CodeQL queries, check out the ``main`` branch.
- This branch represents the very latest version of CodeQL's analysis. Even
- databases created using the most recent version of the CLI may have to be
- upgraded before you can analyze them. For more information, see
- ":doc:`Upgrading CodeQL databases `."
-
- - For the queries used in a particular LGTM Enterprise release, check out the
- branch tagged with the relevant release number. For example, the branch
- tagged ``v1.27.0`` corresponds to LGTM Enterprise 1.27. You must use this
- version if you want to upload data to LGTM Enterprise. For further
- information, see `Preparing CodeQL databases to upload to LGTM
- `__
- in the LGTM admin help.
-
-4. Extract the zip archive
+2. Extract the zip archive
~~~~~~~~~~~~~~~~~~~~~~~~~~
-For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
-simply
-extract the zip archive into the directory you created in step 2.
-
-For example, if the path to your copy of the CodeQL repository is
-``$HOME/codeql-home/codeql-repo``, then extract the CLI into
-``$HOME/codeql-home/``.
+For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
+simply extract the zip archive.
.. container:: toggle
@@ -171,17 +97,17 @@ For example, if the path to your copy of the CodeQL repository is
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina"
-
- macOS "Catalina", "Big Sur", or "Monterey" users should run the following
- commands in the Terminal, where ``${install_loc}`` is the path to the
- directory you created in step 2:
-
- i. ``mv ~/Downloads/codeql*.zip ${install_loc}``
- ii. ``cd ${install_loc}``
+
+ macOS "Catalina", "Big Sur", or "Monterey" users should run the following
+ commands in the Terminal, where ``${extraction-root}`` is the path to the
+ directory where you will extract the CodeQL CLI zip archive:
+
+ i. ``mv ~/Downloads/codeql*.zip ${extraction-root}``
+ ii. ``cd ${extraction-root}``
iii. ``/usr/bin/xattr -c codeql*.zip``
iv. ``unzip codeql*.zip``
-
-5. Launch ``codeql``
+
+3. Launch ``codeql``
~~~~~~~~~~~~~~~~~~~~
Once extracted, you can run CodeQL processes by running the ``codeql``
@@ -191,7 +117,7 @@ executable in a couple of ways:
```` is the folder where you extracted the CodeQL CLI
package.
- By adding ``/codeql`` to your ``PATH``, so that you
- can run the executable as just ``codeql``.
+ can run the executable as just ``codeql``.
At this point, you can execute CodeQL commands. For a full list of the CodeQL
CLI commands, see the "`CodeQL CLI manual <../manual>`__."
@@ -204,7 +130,7 @@ CLI commands, see the "`CodeQL CLI manual <../manual>`__."
":ref:`Setting up CodeQL in Visual Studio Code `."
-6. Verify your CodeQL CLI setup
+4. Verify your CodeQL CLI setup
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CodeQL CLI has subcommands you can execute to verify that you are correctly set
@@ -212,17 +138,20 @@ up to create and analyze databases:
- Run ``codeql resolve languages`` to show which languages are
available for database creation. This will list the languages supported by
- default in your CodeQL CLI package.
-- Run ``codeql resolve qlpacks`` to show which QL packs the CLI can find. This
- will display the names of the QL packs included in the CodeQL repositories:
- ``codeql-cpp``, ``codeql-csharp``, ``codeql-go``,
- ``codeql-java``, ``codeql-javascript``, and ``codeql-python``. The CodeQL
- repositories also contain 'upgrade' packs and 'legacy' packs. Upgrade packs
- are used by the CLI when you want to upgrade a database so that it can be
- analyzed with a newer version of the CodeQL toolchain than was used to create
- it. Legacy packs ensure that custom queries and libraries created using older
- products are compatible with your version of CodeQL.
+ default in your CodeQL CLI package.
+- (Optional) You can download some ":ref"`CodeQL packs ` containing pre-compiled queries you would like to run.
+ To do this, run ``codeql pack download [...pack-name]``, where ``pack-name`` is the name of
+ the pack you want to download. The core query packs are a good place to start. They are:
+ - ``codeql/cpp-queries``
+ - ``codeql/csharp-queries``
+ - ``codeql/java-queries``
+ - ``codeql/javascript-queries``
+ - ``codeql/python-queries``
+ - ``codeql/ruby-queries``
+
+ Alternatively, you can download query packs during the analysis by using the `--download` flag of the `codeql database analyze`
+ command.
.. _using-two-versions-of-the-codeql-cli:
@@ -242,4 +171,4 @@ recommended directory setup depends on which versions you want to install:
directory. For example, if you unpack version 2.0.2 into
``$HOME/codeql-home/codeql-cli``, the older version should be
unpacked into ``$HOME/codeql-older-version/old-codeql-cli``. Here, the common
- grandparent is the ``$HOME`` directory.
+ grandparent is the ``$HOME`` directory.
From 0cd6556964308a48bb57394c1a8265d62fc063ea Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Mon, 17 Jan 2022 10:20:58 -0800
Subject: [PATCH 085/296] Docs: Update analyzing databases docs
Add more information about running packs. Include the `--download` flag.
---
...nalyzing-databases-with-the-codeql-cli.rst | 56 ++++++++++---------
1 file changed, 31 insertions(+), 25 deletions(-)
diff --git a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst
index b28f416f78f..8a5fa1c04d1 100644
--- a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst
@@ -26,6 +26,7 @@ Running ``codeql database analyze``
When you run ``database analyze``, it:
+#. Optionally downloads any referenced CodeQL packages that are not available locally.
#. Executes one or more query files, by running them over a CodeQL database.
#. Interprets the results, based on certain query metadata, so that alerts can be
displayed in the correct location in the source code.
@@ -50,10 +51,13 @@ You must specify:
You can also specify:
-- ````: the queries to run over your database. You can
- list one or more individual query files, specify a directory that will be
- searched recursively for query files, or name a query suite that defines a
- particular set of queries. If omitted, the default query suite for the language
+- ``...``: a list of queries to run over your database. This
+ is a list of arguments. Where each argument can be:
+ - a path to a query file
+ - a path to a directory containing query files
+ - a path to a query suite file
+ - the name of a CodeQL query pack
+ If omitted, the default query suite for the language
of the database being analyzed will be usedFor more information, see the
:ref:`examples ` below.
@@ -63,11 +67,14 @@ You can also specify:
language to the GitHub code scanning API. For more information about this use case,
see `Configuring CodeQL CLI in your CI system `__ in the GitHub documentation.
-- ``--sarif-add-query-help``: (supported in version 2.7.1 onwards) adds any custom query help written
- in markdown to SARIF files (v2.1.0 or later) generated by the analysis. Query help stored in ``.qhelp`` files must be
- converted to ``.md`` before running the analysis. For further information,
+- ``--sarif-add-query-help``: (supported in version 2.7.1 onwards) adds any custom query help written
+ in markdown to SARIF files (v2.1.0 or later) generated by the analysis. Query help stored in ``.qhelp`` files must be
+ converted to ``.md`` before running the analysis. For further information,
see ":ref:`Including query help for custom CodeQL queries in SARIF files `."
+- ``--download``: a boolean flag that will allow the CLI to download any referenced CodeQL packages that are not available locally.
+ If this flag is missing and a referenced CodeQL package is not available locally, the command will fail.
+
- .. include:: ../reusables/threads-query-execution.rst
@@ -119,17 +126,16 @@ Running a CodeQL pack
.. include:: ../reusables/beta-note-package-management.rst
-To run an existing CodeQL query pack from the GitHub Container registry, you need to download it first::
+To run an existing CodeQL query pack from the GitHub Container registry, you can specify one or more
+pack names and use the ``--download`` flag::
- codeql pack download microsoft/coding-standards@1.0.0
+ codeql database analyze --download microsoft/coding-standards@1.0.0 github/secutiry-queries --format=sarifv2.1.0 --output=query-results.sarif
-Afterwards, you can run the pack on a specific database::
-
- codeql database analyze microsoft/coding-standards@1.0.0 / --format=sarifv2.1.0 --output=query-results.sarif
-
-The ``analyze`` command above runs the default suite from ``microsoft/coding-standards v1.0.0`` and the latest version of ``scope/other-pack`` on the specified database.
+The ``analyze`` command above runs the default suite from ``microsoft/coding-standards v1.0.0`` and the latest version of ``github/secutiry-queries`` on the specified database.
For further information about default suites, see ":ref:`Publishing and using CodeQL packs `".
+For more information about CodeQL packs, see :doc:`About CodeQL Packs `.
+
Running query suites
~~~~~~~~~~~~~~~~~~~~
@@ -176,7 +182,7 @@ Integrating a CodeQL pack into a code scanning workflow in GitHub
.. include:: ../reusables/beta-note-package-management.rst
-You can use CodeQL query packs in your Code Scanning setup. This allows you to select query packs published by various sources and use them to analyze your code.
+You can use CodeQL query packs in your Code Scanning setup. This allows you to select query packs published by various sources and use them to analyze your code.
For more information, see "`Using CodeQL query packs in the CodeQL action `_" or "`Downloading and using CodeQL query packs in your CI system `_."
@@ -206,28 +212,28 @@ A SARIF results file is generated. Specifying ``--format=sarif-latest`` ensures
that the results are formatted according to the most recent SARIF specification
supported by CodeQL.
-.. _including-query-help-for-custom-codeql-queries-in-sarif-files:
+.. _including-query-help-for-custom-codeql-queries-in-sarif-files:
-Including query help for custom CodeQL queries in SARIF files
+Including query help for custom CodeQL queries in SARIF files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you use the CodeQL CLI to to run code scanning analyses on third party CI/CD systems,
you can include the query help for your custom queries in SARIF files generated during an analysis.
-After uploading the SARIF file to GitHub, the query help is shown in the code scanning UI for any
-alerts generated by the custom queries.
+After uploading the SARIF file to GitHub, the query help is shown in the code scanning UI for any
+alerts generated by the custom queries.
-From CodeQL CLI 2.7.1 onwards, you can include markdown-rendered query help in SARIF files
+From CodeQL CLI 2.7.1 onwards, you can include markdown-rendered query help in SARIF files
by providing the ``--sarif-add-query-help`` option when running
-``codeql database analyze``.
+``codeql database analyze``.
For more information, see `Configuring CodeQL CLI in your CI system `__
in the GitHub documentation.
You can write query help for custom queries directly in a markdown file and save it alongside the
-corresponding query. Alternatively, for consistency with the standard CodeQL queries,
-you can write query help in the ``.qhelp`` format. Query help written in ``.qhelp``
+corresponding query. Alternatively, for consistency with the standard CodeQL queries,
+you can write query help in the ``.qhelp`` format. Query help written in ``.qhelp``
files can't be included in SARIF files, and they can't be processed by code
-scanning so must be converted to markdown before running
-the analysis. For more information, see ":ref:`Query help files `"
+scanning so must be converted to markdown before running
+the analysis. For more information, see ":ref:`Query help files `"
and ":doc:`Testing query help files `."
Results
From 01b5881de6f4ae805ed1f83055da1855cf7b82b9 Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Tue, 18 Jan 2022 15:48:33 -0800
Subject: [PATCH 086/296] Docs: Remove reference to checking out main branch
We are no longer including information about how to check out
github/codeql, so this paragraph doesn't fit any more.
---
docs/codeql/codeql-cli/upgrading-codeql-databases.rst | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst
index d4f769bc538..4d99ced7a2f 100644
--- a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst
+++ b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst
@@ -4,21 +4,16 @@ Upgrading CodeQL databases
==========================
As the CodeQL CLI tools and queries evolve, you may find that some of your
-CodeQL databases become out of date. You must upgrade out-of-date databases
+CodeQL databases become out of date. You must upgrade out-of-date databases
before you can analyze them.
Databases become out of date when:
- For databases created using the CodeQL CLI, the version of CLI tools used to
- create them is older than your copy of the CodeQL queries.
+ create them is older than your copy of the CodeQL queries.
- For databases downloaded from LGTM.com, the CodeQL tools used by LGTM.com to create
that revision of the code are older than your copy of the CodeQL queries.
-The ``main`` branch of the CodeQL queries is updated more often than both the
-CLI and LGTM.com, so databases are most likely to become out of date if you use
-the queries on this branch. For more information about the different versions of
-the CodeQL queries, see ":ref:`Getting started with the CodeQL CLI `."
-
Out-of-date databases must be upgraded before they can be analyzed. This topic
shows you how to upgrade a CodeQL database using the ``database upgrade``
subcommand.
From a1b0315d90b5bbe04196159ed929eb47ce088ad1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Wed, 19 Jan 2022 00:52:10 +0100
Subject: [PATCH 087/296] Update
cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 43344b589ad..22e42d39147 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -59,7 +59,8 @@ where
// unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
- fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
+ fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT") or
+ fctmp.getArgument(1).getValueText().matches("%O_CREAT%")
) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
From f7240be13675b95fd348f618d3797bedceb21267 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 19 Jan 2022 00:09:52 +0000
Subject: [PATCH 088/296] Add changed framework coverage reports
---
.../library-coverage/coverage.csv | 222 +++++++++---------
.../library-coverage/coverage.rst | 8 +-
2 files changed, 115 insertions(+), 115 deletions(-)
diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv
index 9576ed23eec..ac2c82d2732 100644
--- a/java/documentation/library-coverage/coverage.csv
+++ b/java/documentation/library-coverage/coverage.csv
@@ -1,111 +1,111 @@
-package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
-android.app,7,,84,,,,,,7,,,,,,,,,,,,,,,,,,13,71
-android.content,24,27,96,,,,,,16,,,,,,,,,8,,,,,,,27,,31,65
-android.database,59,,30,,,,,,,,,,,,,,,59,,,,,,,,,30,
-android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,45,15
-android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,41,81
-android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,16,,
-android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,3,,2,,
-androidx.slice,,5,88,,,,,,,,,,,,,,,,,,,,,,5,,27,61
-cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
-com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,62,23
-com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,17
-com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,2,551
-com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,
-com.google.common.io,6,,73,,,,,,,,,,,,,,,,6,,,,,,,,72,1
-com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,
-com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,
-flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1
-groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,
-groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,
-jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
-jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
-jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
-jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
-jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,2,,,,,,,94,55
-java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-java.io,37,,31,,15,,,,,,,,,,,,,,,,22,,,,,,30,1
-java.lang,8,,56,,,,,,,,,,8,,,,,,,,,,,,,,45,11
-java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,3,7,
-java.nio,15,,4,,13,,,,,,,,,,,,,,,,2,,,,,,4,
-java.sql,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
-java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,16,414
-javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
-javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
-javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,
-javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,
-javax.net.ssl,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,
-javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,
-javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,21,2,
-javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,1,,
-javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
-javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
-javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,2,,,,,,,94,55
-javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,1,,,,6,
-javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,3,,,,,,
-jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,10
-net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,5,,,,,
-ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
-org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
-org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
-org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
-org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,22,
-org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
-org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
-org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,293,131
-org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,
-org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
-org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,220,52
-org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,
-org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,1,,2,39,
-org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,2,
-org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,18,6
-org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,2,,3,62,8
-org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,6,,,,,,,,,,
-org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,
-org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,4,4
-org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
-org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,
-org.dom4j,20,,,,,,,,,,,,,,,,,,,,,20,,,,,,
-org.hibernate,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
-org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,
-org.jooq,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,
-org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,198,38
-org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,
-org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,
-org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,2,4
-org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,26
-org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13
-org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,60,10
-org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,10,,,,,,,,,,
-org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,9,,,,,,,,,,
-org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
-org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,
-org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,6,,
-org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,32
-org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,87,52
-org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,13,
-org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,3,,
-org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,8,,
-org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,12,13,
-org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,
-org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,138,25
-org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,3,,
-play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,4,,
-ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
-ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
-ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,48
-ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
-ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
-ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
-ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
+package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
+android.app,16,,103,,,,,,7,,,,,,,,9,,,,,,,,,,,18,85
+android.content,24,27,96,,,,,,16,,,,,,,,,,8,,,,,,,27,,31,65
+android.database,59,,30,,,,,,,,,,,,,,,,59,,,,,,,,,30,
+android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,45,15
+android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,,41,81
+android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,,16,,
+android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,3,,2,,
+androidx.slice,2,5,88,,,,,,,,,,,,,,2,,,,,,,,,5,,27,61
+cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,
+com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,,62,23
+com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,17
+com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,2,551
+com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,,
+com.google.common.io,6,,73,,,,,,,,,,,,,,,,,6,,,,,,,,72,1
+com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,,
+com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,,
+flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1
+groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,
+groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,
+jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,,
+jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23
+jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
+jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,
+jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,2,,,,,,,94,55
+java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+java.io,37,,31,,15,,,,,,,,,,,,,,,,,22,,,,,,31,
+java.lang,8,,58,,,,,,,,,,8,,,,,,,,,,,,,,,46,12
+java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,,3,7,
+java.nio,15,,6,,13,,,,,,,,,,,,,,,,,2,,,,,,6,
+java.sql,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,
+java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,,16,414
+javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,,
+javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23
+javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,
+javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,
+javax.net.ssl,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,,
+javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
+javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,21,2,
+javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,1,,
+javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
+javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,
+javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,2,,,,,,,94,55
+javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,1,,,,6,
+javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,3,,,,,,
+jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,10
+net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,5,,,,,
+ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,
+org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,
+org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783
+org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783
+org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,,22,
+org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,
+org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,
+org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,293,131
+org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,,
+org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,
+org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,220,52
+org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,
+org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,1,,2,39,
+org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,2,
+org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,18,6
+org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,,2,,3,62,8
+org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,,6,,,,,,,,,,
+org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,,
+org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,,4,4
+org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
+org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,
+org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,20,,,,,,
+org.hibernate,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,
+org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,,
+org.jooq,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,,
+org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,198,38
+org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,,
+org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,,
+org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,,2,4
+org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,26
+org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,13
+org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,,60,10
+org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,10,,,,,,,,,,
+org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,9,,,,,,,,,,
+org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
+org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,,
+org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,,
+org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,32
+org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,87,52
+org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13,
+org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,,3,,
+org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,8,,
+org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,12,13,
+org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,,
+org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,138,25
+org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,,
+play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,4,,
+ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4,
+ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10,
+ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,48
+ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35
+ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4,
+ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10,
+ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35
diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst
index 013af21c2da..15a17fe3b34 100644
--- a/java/documentation/library-coverage/coverage.rst
+++ b/java/documentation/library-coverage/coverage.rst
@@ -7,7 +7,7 @@ Java framework & library support
:widths: auto
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission`
- Android,``android.*``,45,392,99,,,3,67,,,
+ Android,``android.*``,45,411,108,,,3,67,,,
`Apache Commons Collections `_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,,
`Apache Commons IO `_,``org.apache.commons.io``,,22,,,,,,,,
`Apache Commons Lang `_,``org.apache.commons.lang3``,,424,,,,,,,,
@@ -15,9 +15,9 @@ Java framework & library support
`Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
`Google Guava `_,``com.google.common.*``,,728,35,,6,,,,,
`JSON-java `_,``org.json``,,236,,,,,,,,
- Java Standard Library,``java.*``,3,529,111,28,,,7,,,10
+ Java Standard Library,``java.*``,3,533,111,28,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
`Spring `_,``org.springframework.*``,29,472,91,,,,19,14,,29
- Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,919,,,,14,18,,
- Totals,,180,5646,1315,28,6,10,107,33,1,66
+ Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,921,,,,14,18,,
+ Totals,,180,5669,1326,28,6,10,107,33,1,66
From f02aeafef137706ca0edbbf611e658ad22587718 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 09:22:01 +0100
Subject: [PATCH 089/296] Ruby: Move regex/non-regex split into `TAstNode` to
convey disjointness
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 41 +++++++++-----------
ruby/ql/lib/codeql/ruby/ast/internal/AST.qll | 40 +++++++++++++++----
2 files changed, 51 insertions(+), 30 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 177b771c73c..569871380a7 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -274,12 +274,10 @@ class StringComponent extends AstNode, TStringComponent {
* "foo#{ bar() } baz"
* ```
*/
-class StringTextComponent extends StringComponent, TStringTextComponent {
+class StringTextComponent extends StringComponent, TStringTextComponentNonRegexp {
private Ruby::Token g;
- StringTextComponent() {
- this = TStringTextComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringTextComponent() { this = TStringTextComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -291,12 +289,10 @@ class StringTextComponent extends StringComponent, TStringTextComponent {
/**
* An escape sequence component of a string or string-like literal.
*/
-class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
+class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponentNonRegexp {
private Ruby::EscapeSequence g;
- StringEscapeSequenceComponent() {
- this = TStringEscapeSequenceComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -309,12 +305,10 @@ class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequen
* An interpolation expression component of a string or string-like literal.
*/
class StringInterpolationComponent extends StringComponent, StmtSequence,
- TStringInterpolationComponent {
+ TStringInterpolationComponentNonRegexp {
private Ruby::Interpolation g;
- StringInterpolationComponent() {
- this = TStringInterpolationComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringInterpolationComponent() { this = TStringInterpolationComponentNonRegexp(g) }
final override string toString() { result = "#{...}" }
@@ -325,14 +319,15 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
+private class TRegExpComponent =
+ TStringTextComponentRegexp or TStringEscapeSequenceComponentRegexp or
+ TStringInterpolationComponentRegexp;
+
/**
* The base class for a component of a regular expression literal.
*/
-class RegExpComponent extends AstNode, TStringComponent {
- private RegExpLiteral parent;
-
- RegExpComponent() { toGenerated(this).getParent() = toGenerated(parent) }
-
+class RegExpComponent extends AstNode, TRegExpComponent {
+ /** Gets the source text for this regex component, if any. */
string getValueText() { none() }
}
@@ -348,10 +343,10 @@ class RegExpComponent extends AstNode, TStringComponent {
* "foo#{ bar() } baz"
* ```
*/
-class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
+class RegExpTextComponent extends RegExpComponent, TStringTextComponentRegexp {
private Ruby::Token g;
- RegExpTextComponent() { this = TStringTextComponent(g) and g.getParent() instanceof Ruby::Regex }
+ RegExpTextComponent() { this = TStringTextComponentRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -367,10 +362,10 @@ class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
/**
* An escape sequence component of a regex literal.
*/
-class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponent {
+class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponentRegexp {
private Ruby::EscapeSequence g;
- RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+ RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponentRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -387,10 +382,10 @@ class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequen
* An interpolation expression component of a regex literal.
*/
class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
- TStringInterpolationComponent {
+ TStringInterpolationComponentRegexp {
private Ruby::Interpolation g;
- RegExpInterpolationComponent() { this = TStringInterpolationComponent(g) }
+ RegExpInterpolationComponent() { this = TStringInterpolationComponentRegexp(g) }
final override string toString() { result = "#{...}" }
diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
index 58df607d4f2..4a95c54e8b3 100644
--- a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
@@ -272,10 +272,25 @@ private module Cached {
TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or
TStringArrayLiteral(Ruby::StringArray g) or
TStringConcatenation(Ruby::ChainedString g) or
- TStringEscapeSequenceComponent(Ruby::EscapeSequence g) or
- TStringInterpolationComponent(Ruby::Interpolation g) or
- TStringTextComponent(Ruby::Token g) {
- g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent
+ TStringEscapeSequenceComponentNonRegexp(Ruby::EscapeSequence g) {
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringEscapeSequenceComponentRegexp(Ruby::EscapeSequence g) {
+ g.getParent() instanceof Ruby::Regex
+ } or
+ TStringInterpolationComponentNonRegexp(Ruby::Interpolation g) {
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringInterpolationComponentRegexp(Ruby::Interpolation g) {
+ g.getParent() instanceof Ruby::Regex
+ } or
+ TStringTextComponentNonRegexp(Ruby::Token g) {
+ (g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringTextComponentRegexp(Ruby::Token g) {
+ (g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
+ g.getParent() instanceof Ruby::Regex
} or
TSubExprReal(Ruby::Binary g) { g instanceof @ruby_binary_minus } or
TSubExprSynth(AST::AstNode parent, int i) { mkSynthChild(SubExprKind(), parent, i) } or
@@ -489,9 +504,12 @@ private module Cached {
n = TSplatParameter(result) or
n = TStringArrayLiteral(result) or
n = TStringConcatenation(result) or
- n = TStringEscapeSequenceComponent(result) or
- n = TStringInterpolationComponent(result) or
- n = TStringTextComponent(result) or
+ n = TStringEscapeSequenceComponentNonRegexp(result) or
+ n = TStringEscapeSequenceComponentRegexp(result) or
+ n = TStringInterpolationComponentNonRegexp(result) or
+ n = TStringInterpolationComponentRegexp(result) or
+ n = TStringTextComponentNonRegexp(result) or
+ n = TStringTextComponentRegexp(result) or
n = TSubExprReal(result) or
n = TSubshellLiteral(result) or
n = TSymbolArrayLiteral(result) or
@@ -680,6 +698,14 @@ class TIntegerLiteral = TIntegerLiteralReal or TIntegerLiteralSynth;
class TBooleanLiteral = TTrueLiteral or TFalseLiteral;
+class TStringTextComponent = TStringTextComponentNonRegexp or TStringTextComponentRegexp;
+
+class TStringEscapeSequenceComponent =
+ TStringEscapeSequenceComponentNonRegexp or TStringEscapeSequenceComponentRegexp;
+
+class TStringInterpolationComponent =
+ TStringInterpolationComponentNonRegexp or TStringInterpolationComponentRegexp;
+
class TStringComponent =
TStringTextComponent or TStringEscapeSequenceComponent or TStringInterpolationComponent;
From 08d48b9375e3bb3a8936f25ec783cf314078bd58 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Wed, 19 Jan 2022 21:42:46 +1300
Subject: [PATCH 090/296] Add top-level doc comment to GraphQL.qll
---
ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
index e6779b65a0f..8f153c917c1 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
@@ -1,3 +1,7 @@
+/**
+ * Provides classes for modelling the `graphql` gem.
+ */
+
private import codeql.ruby.AST
private import codeql.ruby.Concepts
private import codeql.ruby.controlflow.CfgNodes
From ef2eacebce51c046e9f872691277c00cda49ad08 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 15:56:44 +0100
Subject: [PATCH 091/296] add a js/empty-password-in-configuration-file query
---
.../PasswordInConfigurationFileQuery.qll | 50 +++++++++++++++++++
.../CWE-313/PasswordInConfigurationFile.ql | 40 +--------------
.../EmptyPasswordInConfigurationFile.qhelp | 16 ++++++
.../EmptyPasswordInConfigurationFile.ql | 27 ++++++++++
...18-empty-password-in-configuration-file.md | 4 ++
.../EmptyPasswordInConfigurationFile.expected | 6 +++
.../EmptyPasswordInConfigurationFile.qlref | 1 +
.../test/query-tests/Security/CWE-862/tst.js | 1 +
.../query-tests/Security/CWE-862/tst.json | 17 +++++++
.../test/query-tests/Security/CWE-862/tst.yml | 16 ++++++
10 files changed, 140 insertions(+), 38 deletions(-)
create mode 100644 javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll
create mode 100644 javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.qhelp
create mode 100644 javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.ql
create mode 100644 javascript/ql/src/change-notes/2022-01-18-empty-password-in-configuration-file.md
create mode 100644 javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.expected
create mode 100644 javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.qlref
create mode 100644 javascript/ql/test/query-tests/Security/CWE-862/tst.js
create mode 100644 javascript/ql/test/query-tests/Security/CWE-862/tst.json
create mode 100644 javascript/ql/test/query-tests/Security/CWE-862/tst.yml
diff --git a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll
new file mode 100644
index 00000000000..848f924a846
--- /dev/null
+++ b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll
@@ -0,0 +1,50 @@
+/** Classses and predicates for reasoning about passwords in configuration files. */
+
+import javascript
+import semmle.javascript.RestrictedLocations
+import semmle.javascript.security.SensitiveActions
+
+/**
+ * Holds if some JSON or YAML file contains a property with name `key`
+ * and value `val`, where `valElement` is the entity corresponding to the
+ * value.
+ *
+ * The following are excluded by this predicate:
+ * - Dependencies in `package.json` files.
+ * - Values that look like template delimiters.
+ * - Files that appear to be API-specifications, dictonary, test, or example.
+ */
+predicate config(string key, string val, Locatable valElement) {
+ (
+ exists(JSONObject obj | not exists(PackageJSON p | obj = p.getADependenciesObject(_)) |
+ obj.getPropValue(key) = valElement and
+ val = valElement.(JSONString).getValue()
+ )
+ or
+ exists(YAMLMapping m, YAMLString keyElement |
+ m.maps(keyElement, valElement) and
+ key = keyElement.getValue() and
+ (
+ val = valElement.(YAMLString).getValue()
+ or
+ valElement.toString() = "" and
+ val = ""
+ )
+ )
+ ) and
+ // exclude possible templates
+ not val.regexpMatch(Templating::getDelimiterMatchingRegexp()) and
+ not exclude(valElement.getFile())
+}
+
+/**
+ * Holds if file `f` should be excluded because it looks like it may be
+ * an API specification, a dictionary file, or a test or example.
+ */
+predicate exclude(File f) {
+ f.getRelativePath().regexpMatch("(?i).*(^|/)(lang(uage)?s?|locales?|tests?|examples?|i18n)/.*")
+ or
+ f.getStem().regexpMatch("(?i)translations?")
+ or
+ f.getExtension().toLowerCase() = "raml"
+}
diff --git a/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql b/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql
index 1418a219698..eb317b93d67 100644
--- a/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql
+++ b/javascript/ql/src/Security/CWE-313/PasswordInConfigurationFile.ql
@@ -14,47 +14,12 @@
*/
import javascript
-import semmle.javascript.RestrictedLocations
-import semmle.javascript.security.SensitiveActions
-
-/**
- * Holds if some JSON or YAML file contains a property with name `key`
- * and value `val`, where `valElement` is the entity corresponding to the
- * value.
- *
- * Dependencies in `package.json` files are excluded by this predicate.
- */
-predicate config(string key, string val, Locatable valElement) {
- exists(JSONObject obj | not exists(PackageJSON p | obj = p.getADependenciesObject(_)) |
- obj.getPropValue(key) = valElement and
- val = valElement.(JSONString).getValue()
- )
- or
- exists(YAMLMapping m, YAMLString keyElement |
- m.maps(keyElement, valElement) and
- key = keyElement.getValue() and
- val = valElement.(YAMLString).getValue()
- )
-}
-
-/**
- * Holds if file `f` should be excluded because it looks like it may be
- * an API specification, a dictionary file, or a test or example.
- */
-predicate exclude(File f) {
- f.getRelativePath().regexpMatch("(?i).*(^|/)(lang(uage)?s?|locales?|tests?|examples?|i18n)/.*")
- or
- f.getStem().regexpMatch("(?i)translations?")
- or
- f.getExtension().toLowerCase() = "raml"
-}
+import semmle.javascript.security.PasswordInConfigurationFileQuery
from string key, string val, Locatable valElement, string pwd
where
config(key, val, valElement) and
val != "" and
- // exclude possible templates
- not val.regexpMatch(Templating::getDelimiterMatchingRegexp()) and
(
key.toLowerCase() = "password" and
pwd = val and
@@ -66,6 +31,5 @@ where
// look for `password=...`, but exclude `password=;`, `password="$(...)"`,
// `password=%s` and `password==`
pwd = val.regexpCapture("(?is).*password\\s*=\\s*(?!;|\"?[$`]|%s|=)(\\S+).*", 1)
- ) and
- not exclude(valElement.getFile())
+ )
select valElement.(FirstLineOf), "Hard-coded password '" + pwd + "' in configuration file."
diff --git a/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.qhelp b/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.qhelp
new file mode 100644
index 00000000000..b1fe4fb1898
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.qhelp
@@ -0,0 +1,16 @@
+
+
+
+The use of an empty string as a password in a configuration file is not secure.
+
+
+
+Choose a proper password and encrypt it if you need to store it in the configuration file.
+
+
+
+
+
+
diff --git a/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.ql b/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.ql
new file mode 100644
index 00000000000..276b8d3a73c
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-862/EmptyPasswordInConfigurationFile.ql
@@ -0,0 +1,27 @@
+/**
+ * @name Password in configuration file
+ * @description Storing unencrypted passwords in configuration files is unsafe.
+ * @kind problem
+ * @problem.severity warning
+ * @security-severity 7.5
+ * @precision medium
+ * @id js/empty-password-in-configuration-file
+ * @tags security
+ * external/cwe/cwe-258
+ * external/cwe/cwe-862
+ */
+
+import javascript
+import semmle.javascript.security.PasswordInConfigurationFileQuery
+
+from string key, string val, Locatable valElement
+where
+ config(key, val, valElement) and
+ (
+ val = "" and key.toLowerCase() = "password"
+ or
+ key.toLowerCase() != "readme" and
+ // look for `password=;`, `password=`, `password= `, `password==`.
+ val.regexpMatch("(?is).*password\\s*(==?|:)\\s*(\\\"\\\"|''|``|;|:)?\\s*($|;|&|]|\\n).*")
+ )
+select valElement.(FirstLineOf), "Empty password in configuration file."
diff --git a/javascript/ql/src/change-notes/2022-01-18-empty-password-in-configuration-file.md b/javascript/ql/src/change-notes/2022-01-18-empty-password-in-configuration-file.md
new file mode 100644
index 00000000000..4faed7eda00
--- /dev/null
+++ b/javascript/ql/src/change-notes/2022-01-18-empty-password-in-configuration-file.md
@@ -0,0 +1,4 @@
+---
+category: newQuery
+---
+* A new query `js/empty-password-in-configuration-file` has been added. The query detects empty passwords in configuration files. The query is not run by default.
diff --git a/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.expected b/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.expected
new file mode 100644
index 00000000000..227759fd135
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.expected
@@ -0,0 +1,6 @@
+| tst.json:6:17:6:18 | "" | Empty password in configuration file. |
+| tst.json:12:15:12:39 | "userna ... word= " | Empty password in configuration file. |
+| tst.json:15:15:15:38 | "passwo ... me=foo" | Empty password in configuration file. |
+| tst.yml:10:13:10:12 | | Empty password in configuration file. |
+| tst.yml:14:12:14:34 | passwor ... me=foo; | Empty password in configuration file. |
+| tst.yml:16:12:16:38 | passwor ... ="foo"; | Empty password in configuration file. |
diff --git a/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.qlref b/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.qlref
new file mode 100644
index 00000000000..894dcbc7cbb
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-862/EmptyPasswordInConfigurationFile.qlref
@@ -0,0 +1 @@
+Security/CWE-862/EmptyPasswordInConfigurationFile.ql
diff --git a/javascript/ql/test/query-tests/Security/CWE-862/tst.js b/javascript/ql/test/query-tests/Security/CWE-862/tst.js
new file mode 100644
index 00000000000..cc4c41e100b
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-862/tst.js
@@ -0,0 +1 @@
+console.log("foo");
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-862/tst.json b/javascript/ql/test/query-tests/Security/CWE-862/tst.json
new file mode 100644
index 00000000000..662f1920110
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-862/tst.json
@@ -0,0 +1,17 @@
+[
+ {
+ "password": "$pwd"
+ },
+ {
+ "password": ""
+ },
+ {
+ "password": "ff"
+ },
+ {
+ "config": "username=foo&password= "
+ },
+ {
+ "config": "password=&username=foo"
+ }
+]
\ No newline at end of file
diff --git a/javascript/ql/test/query-tests/Security/CWE-862/tst.yml b/javascript/ql/test/query-tests/Security/CWE-862/tst.yml
new file mode 100644
index 00000000000..93af9aad56e
--- /dev/null
+++ b/javascript/ql/test/query-tests/Security/CWE-862/tst.yml
@@ -0,0 +1,16 @@
+steps:
+- script: |
+ PASSWORD="$(PASSWORD)" npm install
+ OTHER_PASSWORD=`get password` yarn install
+username: <%= ENV['USERNAME'] %>
+password: <%= ENV['PASSWORD'] %>
+password: change_me
+others:
+ - one:
+ password:
+ - two:
+ password: <%= ENV['OTHER_PASSWORD'] %>
+ - three:
+ config: password=;username=foo;
+ - four:
+ config: password="";username="foo";
\ No newline at end of file
From 2eea6ca5fd2cc36dc4b2297df2a50f4075a84fa8 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 12:50:22 +0100
Subject: [PATCH 092/296] C#: Example record type with autogenerated
Deconstruct method.
---
.../LocalScopeVariableShadowsMember.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
index 18d5e86dd24..cf3062f8af6 100644
--- a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
+++ b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
@@ -61,4 +61,8 @@ class LocalScopeVariableShadowsMember
{
public C4(int f) { } // GOOD
}
+
+ record class GoodRecordClass(object Prop1, object Prop2) { } // GOOD
+
+ record struct GoodRecordStruct(object Prop1, object Prop2) { } // GOOD
}
From 194da454b1ae7d8edf21da035819ca61e446a855 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 12:51:01 +0100
Subject: [PATCH 093/296] C#: Add record deconstruct method as an exception
from the bad practice rule.
---
.../Declarations/LocalScopeVariableShadowsMember.ql | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
index d3b9135df6e..766fb6d890a 100644
--- a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
+++ b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
@@ -39,6 +39,10 @@ private predicate acceptableShadowing(LocalScopeVariable v, Member m) {
)
or
t.getAConstructor().getAParameter() = v
+ or
+ // Record types have auto-generated Deconstruct methods, which declare an out parameter
+ // with the same name as the property field(s).
+ t.(RecordType).getAMethod("Deconstruct").getAParameter() = v
)
}
From edafdc8fdef140fdfb7c360681d0f648f290cfad Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 14:44:00 +0100
Subject: [PATCH 094/296] C#: Added change note.
---
csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
diff --git a/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
new file mode 100644
index 00000000000..dad981966ba
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The query `cs/local-shadows-member` no longer highlights parameters of `record` types.
\ No newline at end of file
From 71ddd00a6c90fb6a48104919d325b4b717a5087e Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 11:33:03 +0100
Subject: [PATCH 095/296] C#: Workaround Roslyn bug in
`INamedTypeSymbol.TupleElements`
---
.../Entities/Types/TupleType.cs | 2 +-
.../Semmle.Extraction.CSharp/SymbolExtensions.cs | 10 ++++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
index 56db07671d7..d572fe2c267 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init)
{
- tupleElementsLazy = new Lazy(() => Symbol.TupleElements.Select(t => Field.Create(cx, t)).ToArray());
+ tupleElementsLazy = new Lazy(() => Symbol.TupleElementsAdjusted().Select(t => Field.Create(cx, t)).ToArray());
}
// All tuple types are "local types"
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 72ecf842959..80fd1ddd710 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -280,12 +280,18 @@ namespace Semmle.Extraction.CSharp
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
+ ///
+ /// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943
+ ///
+ public static IEnumerable TupleElementsAdjusted(this INamedTypeSymbol type) =>
+ type.TupleElements.Where(f => f is not null && f.Type is not null);
+
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
trapFile.Write('(');
- trapFile.BuildList(",", named.TupleElements,
+ trapFile.BuildList(",", named.TupleElementsAdjusted(),
f =>
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
@@ -464,7 +470,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('(');
trapFile.BuildList(
",",
- namedType.TupleElements.Select(f => f.Type),
+ namedType.TupleElementsAdjusted().Select(f => f.Type),
t => t.BuildDisplayName(cx, trapFile));
trapFile.Write(")");
return;
From d467725ccd49569219311dc457f2125cd8001248 Mon Sep 17 00:00:00 2001
From: Henry Mercer
Date: Wed, 19 Jan 2022 12:08:33 +0000
Subject: [PATCH 096/296] JS: Bump ML-powered query packs to v0.0.5
---
.../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +-
.../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
index 4042feb4c70..963899246f7 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-lib
-version: 0.0.4
+version: 0.0.5
extractor: javascript
library: true
groups:
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
index 2a0dd62d1f8..9fb0fc7ad93 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
@@ -1,6 +1,6 @@
name: codeql/javascript-experimental-atm-queries
language: javascript
-version: 0.0.4
+version: 0.0.5
suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
groups:
From 974a8b1a9a830253db88a23055e336e9fe68bad0 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 12:21:58 +0000
Subject: [PATCH 097/296] C++: Add a test case.
---
.../tests/CleartextTransmission.expected | 4 ++++
.../CWE/CWE-311/semmle/tests/test3.cpp | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index 354ccf9eb53..aacd539c18b 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -84,6 +84,7 @@ edges
| test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
+| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
@@ -195,6 +196,8 @@ nodes
| test3.cpp:352:16:352:23 | password | semmle.label | password |
| test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:353:20:353:27 | password | semmle.label | password |
+| test3.cpp:366:8:366:15 | password | semmle.label | password |
+| test3.cpp:368:15:368:22 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
@@ -226,3 +229,4 @@ subpaths
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
+| test3.cpp:368:3:368:6 | call to recv | test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:366:8:366:15 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index 15e314566d1..2b8fa14a917 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -356,3 +356,21 @@ void test_loops()
}
}
}
+
+void DoDisguisedOperation(char *buffer, size_t size);
+void SecureZeroBuffer(char *buffer, size_t size);
+
+void test_securezero()
+{
+ {
+ char password[256];
+
+ recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted [FALSE POSITIVE]
+
+ DoDisguisedOperation(password, 256); // decryption (disguised)
+
+ // ...
+
+ SecureZeroBuffer(password, 256); // evidence we may have been doing decryption
+ }
+}
From d77ba020f9d0dfc7cfd9717be775a6068073013f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 6 Dec 2021 16:44:13 +0000
Subject: [PATCH 098/296] C++: Support more routines as proof-of-encryption in
cpp/cleartext-transmission.
---
.../src/Security/CWE/CWE-311/CleartextTransmission.ql | 11 ++++++++---
.../semmle/tests/CleartextTransmission.expected | 5 ++++-
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
index 401ffc1b9d6..393bef5ccdc 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
@@ -147,13 +147,18 @@ class NetworkRecv extends NetworkSendRecv {
}
/**
- * An expression that is an argument or return value from an encryption or
- * decryption call.
+ * An expression that is an argument or return value from an encryption /
+ * decryption call. This is quite inclusive to minimize false positives, for
+ * example `SecureZeroMemory` is not an encryption routine but a clue that
+ * encryption may be present.
*/
class Encrypted extends Expr {
Encrypted() {
exists(FunctionCall fc |
- fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and
+ fc.getTarget()
+ .getName()
+ .toLowerCase()
+ .regexpMatch(".*(crypt|encode|decode|hash|securezero).*") and
(
this = fc or
this = fc.getAnArgument()
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index aacd539c18b..bc82a6b2c80 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -85,6 +85,8 @@ edges
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password |
+| test3.cpp:366:8:366:15 | password | test3.cpp:374:3:374:18 | call to SecureZeroBuffer |
+| test3.cpp:366:8:366:15 | password | test3.cpp:374:20:374:27 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
@@ -198,6 +200,8 @@ nodes
| test3.cpp:353:20:353:27 | password | semmle.label | password |
| test3.cpp:366:8:366:15 | password | semmle.label | password |
| test3.cpp:368:15:368:22 | password | semmle.label | password |
+| test3.cpp:374:3:374:18 | call to SecureZeroBuffer | semmle.label | call to SecureZeroBuffer |
+| test3.cpp:374:20:374:27 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
@@ -229,4 +233,3 @@ subpaths
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
-| test3.cpp:368:3:368:6 | call to recv | test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:366:8:366:15 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index 2b8fa14a917..ede9e9c0349 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -365,7 +365,7 @@ void test_securezero()
{
char password[256];
- recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted [FALSE POSITIVE]
+ recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted
DoDisguisedOperation(password, 256); // decryption (disguised)
From c8509cc382fa8630214344894da1707ffa97db85 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 5 Jan 2022 11:54:38 +0100
Subject: [PATCH 099/296] C#: Introduce extractor mode to identify DBs created
with `codeql test run`
---
.../ExtractorOptions.cs | 65 ++++++-------------
.../Semmle.Extraction.CIL.Driver/Program.cs | 7 +-
.../Semmle.Extraction.CIL/Analyser.cs | 10 +--
.../Entities/PdbSourceFile.cs | 2 +-
.../extractor/Semmle.Extraction.CIL/Tuples.cs | 2 +-
.../Entities/Assembly.cs | 2 +-
.../Entities/Attribute.cs | 2 +-
.../Entities/CachedSymbol.cs | 2 +-
.../Entities/Expressions/Invocation.cs | 2 +-
.../Semmle.Extraction.CSharp/Entities/File.cs | 2 +-
.../PreprocessorDirective.cs | 2 +-
.../Entities/Types/NamedType.cs | 2 +-
.../Extractor/Analyser.cs | 2 +-
.../Extractor/StandaloneAnalyser.cs | 2 +-
.../Extractor/TracingAnalyser.cs | 4 +-
.../Populators/TypeContainerVisitor.cs | 2 +-
.../Semmle.Extraction.CSharp/Tuples.cs | 2 +-
csharp/extractor/Semmle.Extraction/Context.cs | 2 +-
.../Semmle.Extraction/Extractor/Extractor.cs | 2 +-
.../Extractor/ExtractorMode.cs | 16 +++++
.../Extractor/StandaloneExtractor.cs | 8 ++-
.../Extractor/TracingExtractor.cs | 9 ++-
csharp/extractor/Semmle.Extraction/Options.cs | 14 +++-
csharp/ql/lib/semmle/code/csharp/File.qll | 14 +++-
24 files changed, 97 insertions(+), 80 deletions(-)
create mode 100644 csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
index 75405d562fe..d5e783ac0a0 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
@@ -6,6 +6,7 @@ using System.Reflection.Metadata;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Globalization;
+using Semmle.Util;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver
@@ -169,18 +170,14 @@ namespace Semmle.Extraction.CIL.Driver
///
/// Parses the command line and collates a list of DLLs/EXEs to extract.
///
- internal class ExtractorOptions
+ internal class ExtractorOptions : CommonOptions
{
private readonly AssemblyList assemblyList = new AssemblyList();
public ExtractorOptions(string[] args)
{
- Verbosity = Verbosity.Info;
- Threads = System.Environment.ProcessorCount;
PDB = true;
- TrapCompression = TrapWriter.CompressionMode.Gzip;
-
- ParseArgs(args);
+ this.ParseArguments(args);
AddFrameworkDirectories(false);
@@ -203,12 +200,6 @@ namespace Semmle.Extraction.CIL.Driver
AddDirectory(RuntimeEnvironment.GetRuntimeDirectory(), extractAll);
}
- public Verbosity Verbosity { get; private set; }
- public bool NoCache { get; private set; }
- public int Threads { get; private set; }
- public bool PDB { get; private set; }
- public TrapWriter.CompressionMode TrapCompression { get; private set; }
-
private void AddFileOrDirectory(string path)
{
path = Path.GetFullPath(path);
@@ -237,43 +228,25 @@ namespace Semmle.Extraction.CIL.Driver
///
public IEnumerable MissingReferences => assemblyList.MissingReferences;
- private void ParseArgs(string[] args)
+ public override bool HandleFlag(string flag, bool value)
{
- foreach (var arg in args)
+ switch (flag)
{
- if (arg == "--verbose")
- {
- Verbosity = Verbosity.All;
- }
- else if (arg == "--silent")
- {
- Verbosity = Verbosity.Off;
- }
- else if (arg.StartsWith("--verbosity:"))
- {
- Verbosity = (Verbosity)int.Parse(arg.Substring(12));
- }
- else if (arg == "--dotnet")
- {
- AddFrameworkDirectories(true);
- }
- else if (arg == "--nocache")
- {
- NoCache = true;
- }
- else if (arg.StartsWith("--threads:"))
- {
- Threads = int.Parse(arg.Substring(10));
- }
- else if (arg == "--no-pdb")
- {
- PDB = false;
- }
- else
- {
- AddFileOrDirectory(arg);
- }
+ case "dotnet":
+ if (value)
+ AddFrameworkDirectories(true);
+ return true;
+ default:
+ return base.HandleFlag(flag, value);
}
}
+
+ public override bool HandleArgument(string argument)
+ {
+ AddFileOrDirectory(argument);
+ return true;
+ }
+
+ public override void InvalidArgument(string argument) { }
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
index 940cd647ed8..9e72f560854 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
@@ -20,11 +20,11 @@ namespace Semmle.Extraction.CIL.Driver
Console.WriteLine(" path A directory/dll/exe to analyze");
}
- private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression)
+ private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, CommonOptions options)
{
var sw = new Stopwatch();
sw.Start();
- Analyser.ExtractCIL(layout, assemblyPath, logger, nocache, extractPdbs, trapCompression, out _, out _);
+ Analyser.ExtractCIL(layout, assemblyPath, logger, options, out _, out _);
sw.Stop();
logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed);
}
@@ -43,8 +43,7 @@ namespace Semmle.Extraction.CIL.Driver
var actions = options.AssembliesToExtract
.Select(asm => asm.Filename)
- .Select(filename =>
- () => ExtractAssembly(layout, filename, logger, options.NoCache, options.PDB, options.TrapCompression))
+ .Select(filename => () => ExtractAssembly(layout, filename, logger, options))
.ToArray();
foreach (var missingRef in options.MissingReferences)
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
index d93d7eb7dc7..e78843148af 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL
/// Whether to extract PDBs.
/// The path of the trap file.
/// Whether the file was extracted (false=cached).
- public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression, out string trapFile, out bool extracted)
+ public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, CommonOptions options, out string trapFile, out bool extracted)
{
trapFile = "";
extracted = false;
@@ -33,14 +33,14 @@ namespace Semmle.Extraction.CIL
{
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
- var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer);
+ var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer, options);
var transformedAssemblyPath = pathTransformer.Transform(assemblyPath);
var project = layout.LookupProjectOrDefault(transformedAssemblyPath);
- using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), trapCompression, discardDuplicates: true);
+ using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), options.TrapCompression, discardDuplicates: true);
trapFile = trapWriter.TrapFile;
- if (nocache || !System.IO.File.Exists(trapFile))
+ if (!options.Cache || !System.IO.File.Exists(trapFile))
{
- ExtractCIL(extractor, trapWriter, extractPdbs);
+ ExtractCIL(extractor, trapWriter, options.PDB);
extracted = true;
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
index 45623b3ceeb..29eb7d118ff 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL.Entities
else
Context.TrapWriter.Archive(TransformedPath, text);
- yield return Tuples.file_extraction_mode(this, 2);
+ yield return Tuples.file_extraction_mode(this, Context.Extractor.Mode | ExtractorMode.Pdb);
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
index d58647aba77..44519f45468 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
@@ -206,7 +206,7 @@ namespace Semmle.Extraction.CIL
internal static Tuple files(File file, string fullName) =>
new Tuple("files", file, fullName);
- internal static Tuple file_extraction_mode(File file, int mode) =>
+ internal static Tuple file_extraction_mode(File file, ExtractorMode mode) =>
new Tuple("file_extraction_mode", file, mode);
internal static Tuple folders(Folder folder, string path) =>
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
index 9555fabec4f..043f8dbf664 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
@@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities
public static Assembly CreateOutputAssembly(Context cx)
{
- if (cx.Extractor.Standalone)
+ if (cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
throw new InternalError("Attempting to create the output assembly in standalone extraction mode");
return AssemblyConstructorFactory.Instance.CreateEntity(cx, outputAssemblyCacheKey, null);
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
index 7e7fc39aab8..a1b976c4a6c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
if (attributeSyntax is not null)
{
- if (!Context.Extractor.Standalone)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
{
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
index 378bda881f7..e03f945175b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
@@ -85,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
// Some built in operators lack locations, so loc is null.
yield return Context.CreateLocation(ReportingLocation);
- if (!Context.Extractor.Standalone && loc.Kind == LocationKind.SourceFile)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && loc.Kind == LocationKind.SourceFile)
yield return Assembly.CreateOutputAssembly(Context);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
index a50b68f75b7..1af93bfe25c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
@@ -129,7 +129,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
.Where(method => method.Parameters.Length >= Syntax.ArgumentList.Arguments.Count)
.Where(method => method.Parameters.Count(p => !p.HasExplicitDefaultValue) <= Syntax.ArgumentList.Arguments.Count);
- return Context.Extractor.Standalone ?
+ return Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) ?
candidates.FirstOrDefault() :
candidates.SingleOrDefault();
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
index fae77b033ad..5d43a7f89d3 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
@@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
- trapFile.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0);
+ trapFile.file_extraction_mode(this, Context.Extractor.Mode);
}
private bool IsPossiblyTextFile()
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
index dba00d61207..a5337bf836c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
@@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.preprocessor_directive_active(this, Symbol.IsActive);
trapFile.preprocessor_directive_location(this, Context.CreateLocation(ReportingLocation));
- if (!Context.Extractor.Standalone)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
{
var compilation = Compilation.Create(Context);
trapFile.preprocessor_directive_compilation(this, compilation);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
index 06c6ccee9a8..e412aa7809d 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
@@ -108,7 +108,7 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var l in GetLocations(Symbol))
yield return Context.CreateLocation(l);
- if (!Context.Extractor.Standalone && Symbol.DeclaringSyntaxReferences.Any())
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && Symbol.DeclaringSyntaxReferences.Any())
yield return Assembly.CreateOutputAssembly(Context);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
index 907948f2408..336a76ffbdc 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
@@ -178,7 +178,7 @@ namespace Semmle.Extraction.CSharp
{
var stopwatch = new Stopwatch();
stopwatch.Start();
- CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, !options.Cache, options.PDB, options.TrapCompression, out var trapFile, out var extracted);
+ CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, options, out var trapFile, out var extracted);
stopwatch.Stop();
ReportProgress(r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
index 23661234f98..9173ab35217 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
@@ -15,7 +15,7 @@ namespace Semmle.Extraction.CSharp
{
compilation = compilationIn;
layout = new Layout();
- extractor = new StandaloneExtractor(Logger, PathTransformer);
+ extractor = new StandaloneExtractor(Logger, PathTransformer, options);
this.options = options;
LogExtractorInfo(Extraction.Extractor.Version);
SetReferencePaths();
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
index 133148723fa..4c15d053a93 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
@@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp
this.layout = new Layout();
this.options = options;
this.compilation = compilation;
- this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer);
+ this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer, options);
LogDiagnostics();
SetReferencePaths();
@@ -188,7 +188,7 @@ namespace Semmle.Extraction.CSharp
{
get
{
- return extractor is null || extractor.Standalone || compilation is null ? Enumerable.Empty() :
+ return extractor is null || extractor.Mode.HasFlag(ExtractorMode.Standalone) || compilation is null ? Enumerable.Empty() :
compilation.
GetDiagnostics().
Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id));
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
index f49a57398ea..0b60fd4fcf0 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
@@ -82,7 +82,7 @@ namespace Semmle.Extraction.CSharp.Populators
public override void VisitAttributeList(AttributeListSyntax node)
{
- if (Cx.Extractor.Standalone)
+ if (Cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
return;
var outputAssembly = Assembly.CreateOutputAssembly(Cx);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
index 028a0259a55..e4b2c3ef8df 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
@@ -451,7 +451,7 @@ namespace Semmle.Extraction.CSharp
internal static void locations_mapped(this System.IO.TextWriter trapFile, NonGeneratedSourceLocation l1, Location l2) =>
trapFile.WriteTuple("locations_mapped", l1, l2);
- internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, int mode) =>
+ internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, ExtractorMode mode) =>
trapFile.WriteTuple("file_extraction_mode", file, mode);
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs
index 99da916d294..2cc1ca440b0 100644
--- a/csharp/extractor/Semmle.Extraction/Context.cs
+++ b/csharp/extractor/Semmle.Extraction/Context.cs
@@ -400,7 +400,7 @@ namespace Semmle.Extraction
private void ReportError(InternalError error)
{
- if (!Extractor.Standalone)
+ if (!Extractor.Mode.HasFlag(ExtractorMode.Standalone))
throw error;
ExtractionError(error);
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
index a40c12d7eee..b16022181df 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
@@ -8,7 +8,7 @@ namespace Semmle.Extraction
///
public abstract class Extractor
{
- public abstract bool Standalone { get; }
+ public abstract ExtractorMode Mode { get; }
///
/// Creates a new extractor instance for one compilation unit.
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
new file mode 100644
index 00000000000..52ef15f52d4
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Semmle.Extraction
+{
+ ///
+ /// The mode in which a file is extracted.
+ ///
+ [Flags]
+ public enum ExtractorMode
+ {
+ None = 0,
+ Standalone = 1,
+ Pdb = 2,
+ QlTest = 4,
+ }
+}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
index 7d4df42ef29..43cf706b306 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
@@ -4,15 +4,19 @@ namespace Semmle.Extraction
{
public class StandaloneExtractor : Extractor
{
- public override bool Standalone => true;
+ private readonly ExtractorMode mode;
+ public override ExtractorMode Mode => mode;
///
/// Creates a new extractor instance for one compilation unit.
///
/// The object used for logging.
/// The object used for path transformations.
- public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer)
+ public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
+ mode = ExtractorMode.Standalone;
+ if (options.QlTest)
+ mode |= ExtractorMode.QlTest;
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
index eb92f35ad6e..4d764f77a11 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
@@ -4,8 +4,8 @@ namespace Semmle.Extraction
{
public class TracingExtractor : Extractor
{
- public override bool Standalone => false;
-
+ private readonly ExtractorMode mode;
+ public override ExtractorMode Mode => mode;
public string OutputPath { get; }
///
@@ -14,9 +14,12 @@ namespace Semmle.Extraction
/// The name of the output DLL/EXE, or null if not specified (standalone extraction).
/// The object used for logging.
/// The object used for path transformations.
- public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer)
+ public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
OutputPath = outputPath;
+ mode = ExtractorMode.None;
+ if (options.QlTest)
+ mode |= ExtractorMode.QlTest;
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Options.cs b/csharp/extractor/Semmle.Extraction/Options.cs
index fffe3c88b4b..fe1c9b33fff 100644
--- a/csharp/extractor/Semmle.Extraction/Options.cs
+++ b/csharp/extractor/Semmle.Extraction/Options.cs
@@ -37,13 +37,18 @@ namespace Semmle.Extraction
///
/// Whether to extract PDB information.
///
- public bool PDB { get; private set; } = false;
+ public bool PDB { get; set; } = false;
///
/// Whether "fast extraction mode" has been enabled.
///
public bool Fast { get; private set; } = false;
+ ///
+ /// Whether extraction is done using `codeql test run`.
+ ///
+ public bool QlTest { get; private set; } = false;
+
///
/// The compression algorithm used for trap files.
///
@@ -70,6 +75,10 @@ namespace Semmle.Extraction
{
switch (flag)
{
+ case "silent":
+ if (value)
+ Verbosity = Verbosity.Off;
+ return true;
case "verbose":
Verbosity = value ? Verbosity.Debug : Verbosity.Error;
return true;
@@ -90,6 +99,9 @@ namespace Semmle.Extraction
CIL = !value;
Fast = value;
return true;
+ case "qltest":
+ QlTest = value;
+ return true;
case "brotli":
TrapCompression = value ? TrapWriter.CompressionMode.Brotli : TrapWriter.CompressionMode.Gzip;
return true;
diff --git a/csharp/ql/lib/semmle/code/csharp/File.qll b/csharp/ql/lib/semmle/code/csharp/File.qll
index f0ee0d6ca7f..5fc0d29e0b6 100644
--- a/csharp/ql/lib/semmle/code/csharp/File.qll
+++ b/csharp/ql/lib/semmle/code/csharp/File.qll
@@ -218,7 +218,12 @@ class File extends Container, @file {
* A source file can come from a PDB and from regular extraction
* in the same snapshot.
*/
- predicate isPdbSourceFile() { file_extraction_mode(this, 2) }
+ predicate isPdbSourceFile() {
+ exists(int i |
+ file_extraction_mode(this, i) and
+ i.bitAnd(2) = 2
+ )
+ }
}
/**
@@ -228,5 +233,10 @@ class SourceFile extends File {
SourceFile() { this.fromSource() }
/** Holds if the file was extracted without building the source code. */
- predicate extractedStandalone() { file_extraction_mode(this, 1) }
+ predicate extractedStandalone() {
+ exists(int i |
+ file_extraction_mode(this, i) and
+ i.bitAnd(1) = 1
+ )
+ }
}
From 4f90b45dd788e2d945e76cc66d4959f7063ae779 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 10:14:44 +0100
Subject: [PATCH 100/296] C#: Address review comments
---
.../Semmle.Extraction.CIL.Driver/ExtractorOptions.cs | 3 +--
.../Semmle.Extraction/Extractor/StandaloneExtractor.cs | 9 +++++----
.../Semmle.Extraction/Extractor/TracingExtractor.cs | 9 +++++----
csharp/extractor/Semmle.Extraction/Options.cs | 2 +-
4 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
index d5e783ac0a0..773d43e40f0 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
@@ -176,8 +176,7 @@ namespace Semmle.Extraction.CIL.Driver
public ExtractorOptions(string[] args)
{
- PDB = true;
- this.ParseArguments(args);
+ this.ParseArguments(args.Append("--pdb").ToArray());
AddFrameworkDirectories(false);
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
index 43cf706b306..4244e34795a 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
@@ -4,8 +4,7 @@ namespace Semmle.Extraction
{
public class StandaloneExtractor : Extractor
{
- private readonly ExtractorMode mode;
- public override ExtractorMode Mode => mode;
+ public override ExtractorMode Mode { get; }
///
/// Creates a new extractor instance for one compilation unit.
@@ -14,9 +13,11 @@ namespace Semmle.Extraction
/// The object used for path transformations.
public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
- mode = ExtractorMode.Standalone;
+ Mode = ExtractorMode.Standalone;
if (options.QlTest)
- mode |= ExtractorMode.QlTest;
+ {
+ Mode |= ExtractorMode.QlTest;
+ }
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
index 4d764f77a11..d43dd891bbe 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
@@ -4,8 +4,7 @@ namespace Semmle.Extraction
{
public class TracingExtractor : Extractor
{
- private readonly ExtractorMode mode;
- public override ExtractorMode Mode => mode;
+ public override ExtractorMode Mode { get; }
public string OutputPath { get; }
///
@@ -17,9 +16,11 @@ namespace Semmle.Extraction
public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
OutputPath = outputPath;
- mode = ExtractorMode.None;
+ Mode = ExtractorMode.None;
if (options.QlTest)
- mode |= ExtractorMode.QlTest;
+ {
+ Mode |= ExtractorMode.QlTest;
+ }
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Options.cs b/csharp/extractor/Semmle.Extraction/Options.cs
index fe1c9b33fff..3ec033c144d 100644
--- a/csharp/extractor/Semmle.Extraction/Options.cs
+++ b/csharp/extractor/Semmle.Extraction/Options.cs
@@ -37,7 +37,7 @@ namespace Semmle.Extraction
///
/// Whether to extract PDB information.
///
- public bool PDB { get; set; } = false;
+ public bool PDB { get; private set; } = false;
///
/// Whether "fast extraction mode" has been enabled.
From d7cd1cf0b9bdc1be77d978822be954397e7291b9 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 19 Jan 2022 13:50:02 +0100
Subject: [PATCH 101/296] C#: Address review comments.
---
.../PreprocessorDirectives/LineDirective.cs | 18 +++++++-----------
.../LineOrSpanDirective.cs | 7 ++++++-
.../LineSpanDirective.cs | 11 +++++------
.../ql/lib/semmle/code/csharp/Preprocessor.qll | 6 ++++--
4 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
index d4075a6f4a9..8f28b97155c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
@@ -8,22 +8,18 @@ namespace Semmle.Extraction.CSharp.Entities
internal class LineDirective : LineOrSpanDirective
{
private LineDirective(Context cx, LineDirectiveTriviaSyntax trivia)
- : base(cx, trivia)
+ : base(cx, trivia, trivia.Line.Kind() switch
+ {
+ SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
+ SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
+ SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
+ _ => throw new InternalError(trivia, "Unhandled line token kind")
+ })
{
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
- var type = Symbol.Line.Kind() switch
- {
- SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
- SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
- SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
- _ => throw new InternalError(Symbol, "Unhandled line token kind")
- };
-
- trapFile.directive_lines(this, type);
-
if (Symbol.Line.IsKind(SyntaxKind.NumericLiteralToken))
{
var value = (int)Symbol.Line.Value!;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
index 546e1571596..20b9ff22a0b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
@@ -15,13 +15,18 @@ namespace Semmle.Extraction.CSharp.Entities
internal abstract class LineOrSpanDirective : PreprocessorDirective where T : LineOrSpanDirectiveTriviaSyntax
{
- protected LineOrSpanDirective(Context cx, T trivia)
+ private readonly LineDirectiveKind kind;
+
+ protected LineOrSpanDirective(Context cx, T trivia, LineDirectiveKind k)
: base(cx, trivia)
{
+ kind = k;
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
+ trapFile.directive_lines(this, kind);
+
if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
{
var file = File.Create(Context, Symbol.File.ValueText);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
index 7d8396d7b04..9f21204731e 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
@@ -8,25 +8,24 @@ namespace Semmle.Extraction.CSharp.Entities
internal class LineSpanDirective : LineOrSpanDirective
{
private LineSpanDirective(Context cx, LineSpanDirectiveTriviaSyntax trivia)
- : base(cx, trivia) { }
+ : base(cx, trivia, LineDirectiveKind.Span) { }
+
public static LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax line) =>
LineSpanDirectiveFactory.Instance.CreateEntity(cx, line, line);
protected override void PopulatePreprocessor(TextWriter trapFile)
{
- trapFile.directive_lines(this, LineDirectiveKind.Span);
-
var startLine = (int)Symbol.Start.Line.Value!;
var startColumn = (int)Symbol.Start.Character.Value!;
var endLine = (int)Symbol.End.Line.Value!;
var endColumn = (int)Symbol.End.Character.Value!;
trapFile.directive_line_span(this, startLine, startColumn, endLine, endColumn);
- var offset = Symbol.CharacterOffset.Value;
- if (offset is not null)
+ if (Symbol.CharacterOffset.Value is int offset)
{
- trapFile.directive_line_offset(this, (int)offset);
+ trapFile.directive_line_offset(this, offset);
}
+
base.PopulatePreprocessor(trapFile);
}
diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
index ac6408440e8..604e43d18b8 100644
--- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
@@ -208,7 +208,9 @@ class HiddenLineDirective extends LineDirective {
override string getAPrimaryQlClass() { result = "HiddenLineDirective" }
}
-abstract private class NumericOrSpanLineDirective extends LineDirective {
+private class NumericOrSpanLineDirective extends LineDirective {
+ NumericOrSpanLineDirective() { directive_lines(this, [2, 3]) }
+
/** Gets the referenced file of this directive. */
File getReferencedFile() { directive_line_file(this, result) }
}
@@ -234,7 +236,7 @@ class SpanLineDirective extends NumericOrSpanLineDirective {
/** Gets the offset of this directive. */
int getOffset() { directive_line_offset(this, result) }
- /** Gets the span of this directive. */
+ /** Holds if the specified start and end positions match this SpanLineDirective. */
predicate span(int startLine, int startColumn, int endLine, int endColumn) {
directive_line_span(this, startLine, startColumn, endLine, endColumn)
}
From 9c2d961ae55a9db6f12a1304a520a2d16cdd3aaa Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 11 Oct 2021 11:17:36 +0100
Subject: [PATCH 102/296] C++: Fix another expression of stdin / stdout we see
in practice.
---
.../Security/CWE/CWE-311/CleartextTransmission.ql | 14 ++++++++++++--
.../semmle/tests/CleartextTransmission.expected | 3 ---
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
index 393bef5ccdc..e2f3742cd2d 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
@@ -105,8 +105,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
* practice it usually isn't very important which query reports a result as
* long as its reported exactly once.
*
- * We do exclude function calls that specify a constant socket, which is
- * likely to mean standard input, standard output or a similar channel.
+ * We do exclude function calls that specify an apparently constant socket,
+ * which is likely to mean standard input, standard output or a similar channel.
*/
abstract class NetworkSendRecv extends FunctionCall {
SendRecv target;
@@ -125,6 +125,16 @@ abstract class NetworkSendRecv extends FunctionCall {
v.getInitializer().getExpr() instanceof Literal and
g = globalValueNumber(v.getAnAccess())
)
+ or
+ // result of a function call with literal inputs (likely constant)
+ exists(FunctionCall fc |
+ forex(Expr arg |
+ arg = fc.getAnArgument() |
+ arg instanceof Literal
+ ) and
+ g = globalValueNumber(fc)
+ )
+ // (this is far from exhaustive)
)
)
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index bc82a6b2c80..298edcb0e71 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -37,7 +37,6 @@ edges
| test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password |
| test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
-| test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password |
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
@@ -147,7 +146,6 @@ nodes
| test3.cpp:217:30:217:37 | password | semmle.label | password |
| test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr |
| test3.cpp:225:34:225:41 | password | semmle.label | password |
-| test3.cpp:227:22:227:29 | password | semmle.label | password |
| test3.cpp:228:26:228:33 | password | semmle.label | password |
| test3.cpp:239:7:239:14 | password | semmle.label | password |
| test3.cpp:241:8:241:15 | password | semmle.label | password |
@@ -225,7 +223,6 @@ subpaths
| test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:129:39:129:47 | password1 | password1 |
| test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:126:9:126:23 | global_password | global_password |
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
-| test3.cpp:227:2:227:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index ede9e9c0349..ed52bcfbe8c 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -224,7 +224,7 @@ int get_socket(int from);
void test_more_stdio(const char *password)
{
- send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output [FALSE POSITIVE]
+ send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output
send(get_socket(val()), password, 128, val()); // BAD
}
From 330b4c3704c59729227717421500e427c3f14743 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 12 Oct 2021 14:04:51 +0100
Subject: [PATCH 103/296] C++: Generalize hasSocketInput a little to include
fgets and friends.
---
.../semmle/code/cpp/models/implementations/Gets.qll | 2 ++
.../semmle/code/cpp/models/interfaces/FlowSource.qll | 10 ++++++----
.../semmle/tests/CleartextTransmission.expected | 3 ---
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
index 407c11834e5..c2dcce138c8 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
@@ -65,4 +65,6 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
+
+ override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
index d454257ea86..6b0a257d6f9 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
@@ -20,8 +20,9 @@ abstract class RemoteFlowSourceFunction extends Function {
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
/**
- * Holds if remote data from this source comes from a socket described by
- * `input`. There is no result if a socket is not specified.
+ * Holds if remote data from this source comes from a socket or stream
+ * described by `input`. There is no result if none is specified by a
+ * parameter.
*/
predicate hasSocketInput(FunctionInput input) { none() }
}
@@ -59,8 +60,9 @@ abstract class RemoteFlowSinkFunction extends Function {
abstract predicate hasRemoteFlowSink(FunctionInput input, string description);
/**
- * Holds if data put into this sink is transmitted through a socket described
- * by `input`. There is no result if a socket is not specified.
+ * Holds if data put into this sink is transmitted through a socket or stream
+ * described by `input`. There is no result if none is specified by a
+ * parameter.
*/
predicate hasSocketInput(FunctionInput input) { none() }
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index 298edcb0e71..0cba8223956 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -39,7 +39,6 @@ edges
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
-| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 |
@@ -149,7 +148,6 @@ nodes
| test3.cpp:228:26:228:33 | password | semmle.label | password |
| test3.cpp:239:7:239:14 | password | semmle.label | password |
| test3.cpp:241:8:241:15 | password | semmle.label | password |
-| test3.cpp:242:8:242:15 | password | semmle.label | password |
| test3.cpp:252:8:252:16 | password1 | semmle.label | password1 |
| test3.cpp:252:24:252:32 | password2 | semmle.label | password2 |
| test3.cpp:254:15:254:23 | password1 | semmle.label | password1 |
@@ -225,7 +223,6 @@ subpaths
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
-| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:268:19:268:26 | password | password |
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index ed52bcfbe8c..65882bf4be2 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -239,7 +239,7 @@ void test_fgets(FILE *stream)
char password[128];
fgets(password, 128, stream); // BAD
- fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input [FALSE POSITIVE]
+ fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input
}
void encrypt_to_buffer(const char *input, char* output);
From acfd593eb417aae1c11ccbe69e1f2b2abe82eaf5 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 12:49:02 +0000
Subject: [PATCH 104/296] C++: Change note.
---
cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
diff --git a/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
new file mode 100644
index 00000000000..4d89ad2eeaf
--- /dev/null
+++ b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.
\ No newline at end of file
From 023049479933aa2341dc7b4771a5a4827f599195 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 13:07:55 +0000
Subject: [PATCH 105/296] C++: Expand QLDoc comment.
---
.../Likely Bugs/Memory Management/ImproperNullTermination.ql | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
index f51c47cf70e..025e50b246f 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
@@ -24,8 +24,8 @@ DeclStmt declWithNoInit(LocalVariable v) {
}
/**
- * Flow from a buffer that is not not null terminated to a sink that requires
- * null termination.
+ * Control flow reachability from a buffer that is not not null terminated to a
+ * sink that requires null termination.
*/
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
From dacb33d1dd0aa68c56fa0b2e5043ff1730990606 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 14:12:21 +0100
Subject: [PATCH 106/296] C#: Adjust Roslyn workaround
---
.../Entities/TypeMention.cs | 6 +++-
.../Entities/Types/TupleType.cs | 14 ++++++---
.../SymbolExtensions.cs | 31 +++++++++++++------
.../Semmle.Extraction/TrapExtensions.cs | 18 +++++++++--
4 files changed, 52 insertions(+), 17 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
index 08a1fa3eb0f..b23ba8ced26 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
@@ -90,7 +90,11 @@ namespace Semmle.Extraction.CSharp.Entities
var tts = (TupleTypeSyntax)syntax;
var tt = (TupleType)type;
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);
- tts.Elements.Zip(tt.TupleElements, (s, t) => Create(Context, s.Type, this, t.Type)).Enumerate();
+ foreach (var (s, t) in tts.Elements.Zip(tt.TupleElements, (s, t) => (s, t?.Type)))
+ {
+ if (t is not null)
+ Create(Context, s.Type, this, t);
+ }
return;
case SyntaxKind.GenericName:
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
index d572fe2c267..f25016b6f59 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init)
{
- tupleElementsLazy = new Lazy(() => Symbol.TupleElementsAdjusted().Select(t => Field.Create(cx, t)).ToArray());
+ tupleElementsLazy = new Lazy(() => Symbol.GetTupleElementsMaybeNull().Select(t => t is null ? null : Field.Create(cx, t)).ToArray());
}
// All tuple types are "local types"
@@ -47,7 +47,10 @@ namespace Semmle.Extraction.CSharp.Entities
var index = 0;
foreach (var element in TupleElements)
- trapFile.tuple_element(this, index++, element);
+ {
+ if (element is not null)
+ trapFile.tuple_element(this, index++, element);
+ }
// Note: symbol.Locations seems to be very inconsistent
// about what locations are available for a tuple type.
@@ -56,9 +59,10 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.type_location(this, Context.CreateLocation(l));
}
- private readonly Lazy tupleElementsLazy;
- public Field[] TupleElements => tupleElementsLazy.Value;
+ private readonly Lazy tupleElementsLazy;
+ public Field?[] TupleElements => tupleElementsLazy.Value;
- public override IEnumerable TypeMentions => TupleElements.Select(e => e.Type);
+ public override IEnumerable TypeMentions =>
+ TupleElements.OfType().Select(e => e.Type);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 80fd1ddd710..26a104286a8 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -283,20 +283,27 @@ namespace Semmle.Extraction.CSharp
///
/// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943
///
- public static IEnumerable TupleElementsAdjusted(this INamedTypeSymbol type) =>
- type.TupleElements.Where(f => f is not null && f.Type is not null);
+ public static IEnumerable GetTupleElementsMaybeNull(this INamedTypeSymbol type) =>
+ type.TupleElements;
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
trapFile.Write('(');
- trapFile.BuildList(",", named.TupleElementsAdjusted(),
- f =>
+ trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
+ (i, f) =>
{
- trapFile.Write((f.CorrespondingTupleField ?? f).Name);
- trapFile.Write(":");
- f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
+ if (f is null)
+ {
+ trapFile.Write($"null({i})");
+ }
+ else
+ {
+ trapFile.Write((f.CorrespondingTupleField ?? f).Name);
+ trapFile.Write(":");
+ f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
+ }
}
);
trapFile.Write(")");
@@ -470,8 +477,14 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('(');
trapFile.BuildList(
",",
- namedType.TupleElementsAdjusted().Select(f => f.Type),
- t => t.BuildDisplayName(cx, trapFile));
+ namedType.GetTupleElementsMaybeNull(),
+ (i, f) =>
+ {
+ if (f is null)
+ trapFile.Write($"null({i})");
+ else
+ f.Type.BuildDisplayName(cx, trapFile);
+ });
trapFile.Write(")");
return;
}
diff --git a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
index e1343019335..5c65e41f0ab 100644
--- a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
@@ -232,19 +232,33 @@ namespace Semmle.Extraction
/// The list of items.
/// The action on each item.
/// The original trap builder (fluent interface).
- public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
+ public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
where T1 : TextWriter
{
var first = true;
+ var i = 0;
foreach (var item in items)
{
if (first)
first = false;
else
trapFile.Write(separator);
- action(item);
+ action(i++, item);
}
return trapFile;
}
+
+ ///
+ /// Builds a trap builder using a separator and an action for each item in the list.
+ ///
+ /// The type of the items.
+ /// The trap builder to append to.
+ /// The separator string (e.g. ",")
+ /// The list of items.
+ /// The action on each item.
+ /// The original trap builder (fluent interface).
+ public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
+ where T1 : TextWriter =>
+ trapFile.BuildList(separator, items, (_, item) => action(item));
}
}
From e4203a41098121f35f544f6ee32e9d3f9053ec2d Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 19 Jan 2022 14:26:34 +0100
Subject: [PATCH 107/296] add CWE-471 to the prototype-pollution queries
---
.../ql/src/Security/CWE-915/PrototypePollutingAssignment.ql | 1 +
javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql | 1 +
2 files changed, 2 insertions(+)
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
index 0557b575adb..2b916426169 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
@@ -13,6 +13,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
index b279c6cbe12..f3143d1cf06 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
@@ -12,6 +12,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
From b27d315ff4215a1b48c20130adb1e0aa6d93bc72 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:30:27 +0000
Subject: [PATCH 108/296] Ruby: add an example of `protect_from_forgery with:
:exception`
---
.../cwe-352/railsapp/app/controllers/articles_controller.rb | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
index 2a0037f4b25..6b1d1411a39 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -1,5 +1,9 @@
class ArticlesController < ApplicationController
- prepend_before_action :user_authored_article?, only: [:delete_authored_article]
+ prepend_before_action :user_authored_article?, only: [:delete_authored_article, :change_title]
+
+ # GOOD: `with: :exception` provides more effective CSRF protection than
+ # `with: :null_session` or `with: :reset_session`.
+ protect_from_forgery with: :exception, only: [:change_title]
def delete_authored_article
article.destroy
From 45ed5a806c04bcfb0194e1b16e34015b73057743 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:37:28 +0000
Subject: [PATCH 109/296] Ruby: changenote for rb/csrf-protection-disabled
enhancement
---
.../src/change-notes/2022-01-19-csrf-protection-weakened.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
diff --git a/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md b/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
new file mode 100644
index 00000000000..55477a11cec
--- /dev/null
+++ b/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+lgtm,codescanning
+* The query `rb/csrf-protection-disabled` has been extended to find calls to the Rails method `protect_from_forgery` that may weaken CSRF protection.
From 0aab670b17eb710825bd77c8379e157bd524d1fc Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:47:00 +0000
Subject: [PATCH 110/296] Ruby: add missing example rails action
---
.../cwe-352/railsapp/app/controllers/articles_controller.rb | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
index 6b1d1411a39..e4b43e00e7a 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -9,6 +9,11 @@ class ArticlesController < ApplicationController
article.destroy
end
+ def change_title
+ article.title = params[:article_title]
+ article.save!
+ end
+
def article
@article ||= Article.find(params[:article_id])
end
From cb9e14f54410a184eeea94792ea712df136e8d12 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 19 Jan 2022 14:54:57 +0100
Subject: [PATCH 111/296] add cwe-471 to js/prototype-pollution
---
.../ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
index f74699dcfed..e3cebbc3f7c 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
@@ -13,6 +13,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
From f0645a34b97cfc63158476b70821011e26b31f48 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 19 Jan 2022 14:06:40 +0000
Subject: [PATCH 112/296] Remove security-severity tag instead
This leaves the Java query in the same state as its C# cousin.
---
java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql | 2 --
1 file changed, 2 deletions(-)
diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
index 6bf44839dd4..a18df356899 100644
--- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
+++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
@@ -4,12 +4,10 @@
* guarantee an evenly distributed sequence of random numbers.
* @kind problem
* @problem.severity warning
- * @security-severity 9.8
* @precision medium
* @id java/random-used-once
* @tags reliability
* maintainability
- * security
* external/cwe/cwe-335
*/
From f3daff4e5a2e246e3455cec88b84c02299367635 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 19 Jan 2022 15:13:06 +0100
Subject: [PATCH 113/296] Python: Add FP tests for cleartext logging
---
.../dataflow/sensitive-data/test.py | 13 ++++++++
.../CleartextLogging.expected | 20 +++++++++++++
.../Security/CWE-312-CleartextLogging/test.py | 30 +++++++++++++++++++
.../CleartextStorage.expected | 4 +++
.../Security/CWE-312-CleartextStorage/test.py | 11 +++++++
5 files changed, 78 insertions(+)
diff --git a/python/ql/test/experimental/dataflow/sensitive-data/test.py b/python/ql/test/experimental/dataflow/sensitive-data/test.py
index a831115e01d..626bc771118 100644
--- a/python/ql/test/experimental/dataflow/sensitive-data/test.py
+++ b/python/ql/test/experimental/dataflow/sensitive-data/test.py
@@ -112,3 +112,16 @@ print(foo) # $ SensitiveUse=password
harmless = lambda: "bar"
bar = call_wrapper(harmless)
print(bar) # $ SPURIOUS: SensitiveUse=password
+
+# ------------------------------------------------------------------------------
+# cross-talk in dictionary.
+# ------------------------------------------------------------------------------
+
+from unknown_settings import password # $ SensitiveDataSource=password
+
+print(password) # $ SensitiveUse=password
+_config = {"sleep_timer": 5, "mysql_password": password}
+
+# since we have taint-step from store of `password`, we will consider any item in the
+# dictionary to be a password :(
+print(_config["sleep_timer"]) # $ SPURIOUS: SensitiveUse=password
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
index 3aacfa32aa5..51ee9af5309 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
@@ -4,6 +4,11 @@ edges
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password |
+| test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account |
+| test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring |
+| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x |
+| test.py:65:14:68:5 | ControlFlowNode for Dict | test.py:69:11:69:31 | ControlFlowNode for Subscript |
+| test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:65:14:68:5 | ControlFlowNode for Dict |
nodes
| test.py:19:16:19:29 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:20:48:20:55 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -15,6 +20,16 @@ nodes
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
+| test.py:43:9:43:15 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
+| test.py:43:18:43:27 | ControlFlowNode for account_id | semmle.label | ControlFlowNode for account_id |
+| test.py:46:11:46:17 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
+| test.py:50:18:50:51 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
+| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
+| test.py:56:11:56:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
+| test.py:60:50:60:70 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| test.py:65:14:68:5 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict |
+| test.py:67:21:67:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
subpaths
#select
| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
@@ -26,3 +41,8 @@ subpaths
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) |
+| test.py:46:11:46:17 | ControlFlowNode for account | test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account | $@ is logged here. | test.py:43:9:43:15 | ControlFlowNode for account | Sensitive data (id) |
+| test.py:50:18:50:51 | ControlFlowNode for Fstring | test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring | $@ is logged here. | test.py:43:18:43:27 | ControlFlowNode for account_id | Sensitive data (id) |
+| test.py:56:11:56:11 | ControlFlowNode for x | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x | $@ is logged here. | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
+| test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | $@ is logged here. | test.py:60:50:60:70 | ControlFlowNode for Attribute | Sensitive data (id) |
+| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | $@ is logged here. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
index a20f2cc708c..f3dd31543a6 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
@@ -39,6 +39,36 @@ def print_password():
sys.stdout.write(get_password()) # NOT OK
sys.stderr.write(get_password()) # NOT OK
+
+def FPs(account, account_id):
+ # we assume that any account parameter is sensitive (id/username)
+ # https://github.com/github/codeql/issues/6363
+ print(account) # OK
+
+ # https://github.com/github/codeql/issues/6927
+ arn = f"arn:aws:iam::{account_id}:role/cfripper-access"
+ logging.info(f"Preparing to assume role: {arn}") # OK
+
+ # Harmless UUIDs
+ # https://github.com/github/codeql/issues/6726
+ # https://github.com/github/codeql/issues/7497
+ x = generate_uuid4()
+ print(x) # OK
+
+ # username not considered sensitive
+ # https://github.com/github/codeql/issues/7116
+ logging.error("Misc Exception. User %s: %s", request.user.username)
+
+ # dictionary taint-flow corss-talk
+ # https://github.com/github/codeql/issues/6380
+ import settings
+ config = {
+ "sleep_timer": 5,
+ "password": settings.password
+ }
+ print(config["sleep_timer"]) # OK
+
+
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
log_password()
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
index 518935eb677..3f453244813 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
@@ -4,6 +4,7 @@ edges
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:9:17:9:29 | ControlFlowNode for List |
| test.py:9:17:9:29 | ControlFlowNode for List | test.py:10:25:10:29 | ControlFlowNode for lines |
+| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x |
nodes
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -13,9 +14,12 @@ nodes
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:9:17:9:29 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
+| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
+| test.py:21:20:21:20 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
subpaths
#select
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
+| test.py:21:20:21:20 | ControlFlowNode for x | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x | $@ is stored here. | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
index c085806d389..f232f1a2ad6 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
@@ -8,3 +8,14 @@ def write_cert(filename):
file.write(cert) # NOT OK
lines = [cert + "\n"]
file.writelines(lines) # NOT OK
+
+def FPs():
+ # just like for cleartext-logging see that file for more elaborate tests
+ #
+ # this part is just to make sure the two queries are in line with what is considered
+ # sensitive information.
+
+ with open(filename, "w") as file:
+ # Harmless UUIDs
+ x = generate_uuid4()
+ file.write(x) # OK
From c63fcb2c696061154d46d31cc8f69f0639783415 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 19 Jan 2022 14:13:45 +0000
Subject: [PATCH 114/296] Add change note
---
java/ql/src/change-notes/2022-01-19-random-used-once.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 java/ql/src/change-notes/2022-01-19-random-used-once.md
diff --git a/java/ql/src/change-notes/2022-01-19-random-used-once.md b/java/ql/src/change-notes/2022-01-19-random-used-once.md
new file mode 100644
index 00000000000..f9a00c6528f
--- /dev/null
+++ b/java/ql/src/change-notes/2022-01-19-random-used-once.md
@@ -0,0 +1,4 @@
+---
+category: queryMetadata
+---
+* The "Random used only once" (`java/random-used-once`) query no longer has a `security-severity` score. This has been causing some tools to categorise it as a security query, when it is more useful as a code-quality query.
From e82e648ca15714c0a6f38b900fa7a15841f3c9c8 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 19 Jan 2022 15:25:21 +0100
Subject: [PATCH 115/296] Python: Remove usernames as sensitive source for
cleartext queries
Closes #6363, #6927, #6726, #7497, #7116
---
.../dataflow/CleartextLoggingCustomizations.qll | 4 ++++
.../dataflow/CleartextStorageCustomizations.qll | 4 ++++
.../2021-01-19-remove-cleartext-fps.md | 4 ++++
.../CleartextLogging.expected | 14 --------------
.../CleartextStorage.expected | 4 ----
5 files changed, 12 insertions(+), 18 deletions(-)
create mode 100644 python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
index 72530536d8e..fcf8885f3f4 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
@@ -40,6 +40,10 @@ module CleartextLogging {
* A source of sensitive data, considered as a flow source.
*/
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
+ SensitiveDataSourceAsSource() {
+ not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
+ }
+
override SensitiveDataClassification getClassification() {
result = SensitiveDataSource.super.getClassification()
}
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
index 3aaf7acf89f..3c7bc43ffa2 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
@@ -39,6 +39,10 @@ module CleartextStorage {
* A source of sensitive data, considered as a flow source.
*/
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
+ SensitiveDataSourceAsSource() {
+ not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
+ }
+
override SensitiveDataClassification getClassification() {
result = SensitiveDataSource.super.getClassification()
}
diff --git a/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md b/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
new file mode 100644
index 00000000000..0ddb4d804fd
--- /dev/null
+++ b/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
@@ -0,0 +1,4 @@
+---
+category: majorAnalysis
+---
+* No longer consider usernames or other account information as sensitive data for the queries `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data`, since this has lead to many false positives.
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
index 51ee9af5309..f5fb2ac8dfb 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
@@ -4,9 +4,6 @@ edges
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password |
-| test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account |
-| test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring |
-| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x |
| test.py:65:14:68:5 | ControlFlowNode for Dict | test.py:69:11:69:31 | ControlFlowNode for Subscript |
| test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:65:14:68:5 | ControlFlowNode for Dict |
nodes
@@ -20,13 +17,6 @@ nodes
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
-| test.py:43:9:43:15 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
-| test.py:43:18:43:27 | ControlFlowNode for account_id | semmle.label | ControlFlowNode for account_id |
-| test.py:46:11:46:17 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
-| test.py:50:18:50:51 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
-| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
-| test.py:56:11:56:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
-| test.py:60:50:60:70 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:65:14:68:5 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict |
| test.py:67:21:67:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
@@ -41,8 +31,4 @@ subpaths
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) |
-| test.py:46:11:46:17 | ControlFlowNode for account | test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account | $@ is logged here. | test.py:43:9:43:15 | ControlFlowNode for account | Sensitive data (id) |
-| test.py:50:18:50:51 | ControlFlowNode for Fstring | test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring | $@ is logged here. | test.py:43:18:43:27 | ControlFlowNode for account_id | Sensitive data (id) |
-| test.py:56:11:56:11 | ControlFlowNode for x | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x | $@ is logged here. | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
-| test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | $@ is logged here. | test.py:60:50:60:70 | ControlFlowNode for Attribute | Sensitive data (id) |
| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | $@ is logged here. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
index 3f453244813..518935eb677 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
@@ -4,7 +4,6 @@ edges
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:9:17:9:29 | ControlFlowNode for List |
| test.py:9:17:9:29 | ControlFlowNode for List | test.py:10:25:10:29 | ControlFlowNode for lines |
-| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x |
nodes
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -14,12 +13,9 @@ nodes
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:9:17:9:29 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
-| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
-| test.py:21:20:21:20 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
subpaths
#select
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
-| test.py:21:20:21:20 | ControlFlowNode for x | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x | $@ is stored here. | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
From 51e8b4c7edbbf4226283da1e703db1eaa46343ff Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Wed, 19 Jan 2022 14:26:52 +0000
Subject: [PATCH 116/296] Port changes from main to rc/3.3 to avoid regression
---
docs/codeql/support/ql-training.rst | 30 ++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/docs/codeql/support/ql-training.rst b/docs/codeql/support/ql-training.rst
index bb4dc9a3f2e..6eb8019e5c9 100644
--- a/docs/codeql/support/ql-training.rst
+++ b/docs/codeql/support/ql-training.rst
@@ -25,7 +25,7 @@ When you have selected a presentation, use |arrow-r| and |arrow-l| to navigate b
Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode.
The presentations contain a number of query examples.
-We recommend that you download `CodeQL for Visual Studio Code `__ and add the example database for each presentation so that you can find the bugs mentioned in the slides.
+We recommend that you download `CodeQL for Visual Studio Code `__ and add the example database for each presentation so that you can find the bugs mentioned in the slides.
.. pull-quote::
@@ -39,25 +39,25 @@ We recommend that you download `CodeQL for Visual Studio Code `__–an introduction to variant analysis and CodeQL for C/C++ programmers.
-- `Example: Bad overflow guard `__–an example of iterative query development to find bad overflow guards in a C++ project.
-- `Program representation: CodeQL for C/C++ `__–information on how CodeQL analysis represents C/C++ programs.
-- `Introduction to local data flow `__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
-- `Exercise: snprintf overflow `__–an example demonstrating how to develop a data flow query.
-- `Introduction to global data flow `__–an introduction to analyzing global data flow in C/C++ using CodeQL.
-- `Analyzing control flow: CodeQL for C/C++ `__–an introduction to analyzing control flow in C/C++ using CodeQL.
+- `Introduction to variant analysis: CodeQL for C/C++ `__–an introduction to variant analysis and CodeQL for C/C++ programmers.
+- `Example: Bad overflow guard `__–an example of iterative query development to find bad overflow guards in a C++ project.
+- `Program representation: CodeQL for C/C++ `__–information on how CodeQL analysis represents C/C++ programs.
+- `Introduction to local data flow `__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
+- `Exercise: snprintf overflow `__–an example demonstrating how to develop a data flow query.
+- `Introduction to global data flow `__–an introduction to analyzing global data flow in C/C++ using CodeQL.
+- `Analyzing control flow: CodeQL for C/C++ `__–an introduction to analyzing control flow in C/C++ using CodeQL.
CodeQL and variant analysis for Java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- `Introduction to variant analysis: CodeQL for Java `__–an introduction to variant analysis and CodeQL for Java programmers.
-- `Example: Query injection `__–an example of iterative query development to find unsanitized SPARQL injections in a Java project.
-- `Program representation: CodeQL for Java `__–information on how CodeQL analysis represents Java programs.
-- `Introduction to local data flow `__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
-- `Exercise: Apache Struts `__–an example demonstrating how to develop a data flow query.
-- `Introduction to global data flow `__–an introduction to analyzing global data flow in Java using CodeQL.
+- `Introduction to variant analysis: CodeQL for Java `__–an introduction to variant analysis and CodeQL for Java programmers.
+- `Example: Query injection `__–an example of iterative query development to find unsanitized SPARQL injections in a Java project.
+- `Program representation: CodeQL for Java `__–information on how CodeQL analysis represents Java programs.
+- `Introduction to local data flow `__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE.
+- `Exercise: Apache Struts `__–an example demonstrating how to develop a data flow query.
+- `Introduction to global data flow `__–an introduction to analyzing global data flow in Java using CodeQL.
Further reading
~~~~~~~~~~~~~~~
-- `GitHub Security Lab